docs: def cli(ctx):
      """
      Run setup after a fresh Vagrant installation.
      """
      log = logging.getLogger('ipsv.setup')
      assert isinstance(ctx, Context)
  
      lock_path = os.path.join(ctx.config.get('Paths', 'Data'), 'setup.lck')
      if os.path.exists(lock_path):
          raise Exception('Setup is locked, please remove the setup lock file to continue')
  
      # Create our package directories
      p = Echo('Creating IPS Vagrant system directories...')
      dirs = ['/etc/ipsv', ctx.config.get('Paths', 'Data'), ctx.config.get('Paths', 'Log'),
              ctx.config.get('Paths', 'NginxSitesAvailable'), ctx.config.get('Paths', 'NginxSitesEnabled'),
              ctx.config.get('Paths', 'NginxSSL')]
      for d in dirs:
          if not os.path.exists(d):
              os.makedirs(d, 0o755)
      p.done()
  
      p = Echo('Copying IPS Vagrant configuration files...')
      with open('/etc/ipsv/ipsv.conf', 'w+') as f:
          ctx.config.write(f)
      p.done()
  
      # Set up alembic
      alembic_cfg = Config(os.path.join(ctx.basedir, 'alembic.ini'))
      alembic_cfg.set_main_option("script_location", os.path.join(ctx.basedir, 'migrations'))
      alembic_cfg.set_main_option("sqlalchemy.url", "sqlite:////{path}"
                                  .format(path=os.path.join(ctx.config.get('Paths', 'Data'), 'sites.db')))
  
      command.current(alembic_cfg)
      command.downgrade(alembic_cfg, 'base')
      command.upgrade(alembic_cfg, 'head')
  
      # Update the system
      p = Echo('Updating package cache...')
      cache = apt.Cache()
      cache.update()
      cache.open(None)
      p.done()
      p = Echo('Upgrading system packages...')
      cache.upgrade()
      cache.commit()
      p.done()
  
      # Install our required packages
      requirements = ['nginx', 'php5-fpm', 'php5-curl', 'php5-gd', 'php5-imagick', 'php5-json', 'php5-mysql',
                      'php5-readline', 'php5-apcu', 'php5-xdebug']
  
      for requirement in requirements:
          # Make sure the package is available
          p = Echo('Marking package {pkg} for installation'.format(pkg=requirement))
          if requirement not in cache:
              log.warn('Required package {pkg} not available'.format(pkg=requirement))
              p.done(p.FAIL)
              continue
  
          # Mark the package for installation
          cache[requirement].mark_install()
          p.done()
  
      log.info('Committing package cache')
      p = Echo('Downloading and installing packages...')
      cache.commit()
      p.done()
  
      # Disable the default server block
      p = Echo('Configuring Nginx...')
      default_available = os.path.join(ctx.config.get('Paths', 'NginxSitesAvailable'), 'default')
      default_enabled = os.path.join(ctx.config.get('Paths', 'NginxSitesEnabled'), 'default')
      if os.path.isfile(default_available):
          os.remove(default_available)
      if os.path.islink(default_enabled):
          os.unlink(default_enabled)
      p.done()
  
      # Restart Nginx
      FNULL = open(os.devnull, 'w')
      p = Echo('Restarting Nginx...')
      subprocess.check_call(['service', 'nginx', 'restart'], stdout=FNULL, stderr=subprocess.STDOUT)
      p.done()
  
      # php.ini configuration
      p = Echo('Configuring php...')
      with open('/etc/php5/fpm/php.ini', 'a') as f:
          f.write('\n[XDebug]')
          f.write('\nxdebug.cli_color=1')
  
      temp_fh, temp_path = mkstemp()
      with open(temp_path, 'w') as nf:
          with open('/etc/php5/fpm/php.ini') as of:
              # Configuration options we are replacing
              upload_max_filesize = re.compile( '^upload_max_filesize\s+=\s+(\d+[a-zA-Z])\s*$' )
              post_max_size = re.compile( '^post_max_size\s+=\s+(\d+[a-zA-Z])\s*$' )
  
              for line in of:
                  match = upload_max_filesize.match( line ) if upload_max_filesize is not True else False
                  if match:
                      nf.write( 'upload_max_filesize = 1000M\n' )
                      upload_max_filesize = True
                      continue
  
                  match = post_max_size.match( line ) if post_max_size is not True else False
                  if match:
                      nf.write( 'post_max_size = 1000M\n' )
                      post_max_size = True
                      continue
  
                  nf.write(line)
      os.close(temp_fh)
      os.remove('/etc/php5/fpm/php.ini')
      shutil.move(temp_path, '/etc/php5/fpm/php.ini')
      os.chmod('/etc/php5/fpm/php.ini', 0o644)
      p.done()
  
      # php5-fpm configuration
      p = Echo('Configuring php5-fpm...')
      if os.path.isfile('/etc/php5/fpm/pool.d/www.conf'):
          os.remove('/etc/php5/fpm/pool.d/www.conf')
  
      fpm_config = FpmPoolConfig().template
      with open('/etc/php5/fpm/pool.d/ips.conf', 'w') as f:
          f.write(fpm_config)
      p.done()
  
      # Restart php5-fpm
      p = Echo('Restarting php5-fpm...')
      subprocess.check_call(['service', 'php5-fpm', 'restart'], stdout=FNULL, stderr=subprocess.STDOUT)
      p.done()
  
      # Copy the man pages and rebuild the manual database
      p = Echo('Writing manual pages...')
      man_path = os.path.join(ctx.basedir, 'man', 'ipsv.1')
      sys_man_path = '/usr/local/share/man/man1'
      if not os.path.exists(sys_man_path):
          os.makedirs(sys_man_path)
  
      shutil.copyfile(man_path, os.path.join(sys_man_path, 'ipsv.1'))
  
      subprocess.check_call(['mandb'], stdout=FNULL, stderr=subprocess.STDOUT)
  
      # Enable the welcome message
      log.debug('Writing welcome message')
      wm_header = '## DO NOT REMOVE :: AUTOMATICALLY GENERATED BY IPSV ##'
      wm_remove = False
  
      # Remove old profile data
      for line in fileinput.input('/etc/profile', inplace=True):
          # Header / footer match?
          if line == wm_header:
              # Footer match (Stop removing)
              if wm_remove:
                  wm_remove = False
                  continue
  
              # Header match (Start removing)
              wm_remove = True
              continue
  
          # Removing lines?
          if wm_remove:
              continue
  
          # Print line and continue as normal
          sys.stdout.write(line)
  
      # Write new profile data
      with open('/etc/profile', 'a') as f:
          f.write("\n" + wm_header + "\n")
          fl_lock_path = os.path.join(ctx.config.get('Paths', 'Data'), 'first_login.lck')
          f.write('if [ ! -f "{lp}" ]; then'.format(lp=fl_lock_path) + "\n")
          f.write('  less "{wp}"'.format(wp=os.path.join(ctx.basedir, 'WELCOME.rst')) + "\n")
          f.write('  sudo touch "{lp}"'.format(lp=fl_lock_path) + "\n")
          f.write('fi' + "\n")
          f.write(wm_header + "\n")
      p.done()
  
      log.debug('Writing setup lock file')
      with open(os.path.join(ctx.config.get('Paths', 'Data'), 'setup.lck'), 'w') as f:
          f.write('1')