Skip to content

Deployment (Debian)

wvengen edited this page Mar 11, 2016 · 38 revisions

We're using a Debian virtual machine at greenhost.nl to host foodsoft instances. This page is a log of things there were needed to get a deployed website. There's also an older page on deployment on CentOS.

General system setup

  • Creation of users, public-key ssh access (disabled ssh password authentication)
  • Set hostname
  • Setup firewall
    • apt-get install iptables-persistent
    • edit /etc/iptables/rules.v[46], e.g. see here
    • for IPv6, you can use icmp6-adm-prohibited instead of icmp-host-prohibited
  • Be able to send mail, apt-get install postfix configure as internet site
  • In case IPv6 is misconfigured at your hosting provider, see this.

Ruby setup

  • Multi-user RVM install need to run as normal user deploy using sudo

    sudo apt-get install curl bzip2 git-core subversion build-essential
    \curl -sSL https://get.rvm.io | sudo bash -s stable

    Then add that user to the rvm group.

  • Disable installation of documentation, add to /etc/gemrc (from here):

    gem: --no-rdoc --no-ri
    
  • Install Ruby: rvm install 2.2, this will install it for all users.

Apache setup

  • apt-get install apache2-mpm-worker

  • install Passenger from its apt repository

    apt-get install apt-transport-https
    echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger wheezy main" >>/etc/apt/sources.list
    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
    apt-get install apache2-mpm-worker libapache2-mod-passenger
  • Disable cgi-bin (comment lines) in /etc/apache2/sites-available/default and default-ssl

  • set ServerName, set ServerAdmin in /etc/apache2/sites-available/default (globally, outside VirtualHost)

  • Setup SSL

    • Install letsencrypt
    • Obtain certificate with letsencrypt-auto certonly --webroot -w /var/www -d order.foodcoop.nl
    • a2enmod ssl && a2ensite default-ssl
    • Set SSLCertificateFile, SSLCertificateKeyFile and SSLCertificateChainFile (in /etc/sites-enabled/default-ssl) - see where letsencrypt put them
    • check configuration at SSL Labs (or at gogetssl)
    • redirect all to https in http config: Redirect permanent / https://order.foodcoop.nl/
  • Setup administration area in /etc/apache2/sites-available/default-ssl httpd.conf ## Administration tools <Location /admin> AllowOverride None AuthType Basic AuthName "Admin Tools" AuthUserFile "/etc/apache2/adminusers.htpasswd" Require valid-user </Location> <Location /admin/server-status> SetHandler server-status </Location>

    • Tweak server-status in /etc/apache2/mods-enabled/status.conf (disable default!)
  • Use default rvm Ruby for passenger, create /etc/apache2/conf.d/passenger.conf:

    PassengerDefaultRuby /usr/local/rvm/wrappers/default/ruby
    

Webstats

  • Install awstats and setup users - according to here:

    apt-get install --install-suggests awstats
    addgroup --system awstats
    adduser --system --home /var/lib/awstats --disabled-password --disabled-login --ingroup awstats awstats
    adduser awstats adm
    chown -R awstats:awstats /var/lib/awstats/ /var/cache/awstats
  • Setup default AWStats configuration in /etc/awstats/awstats.conf.local:

    EnableLockForUpdate=1
    CreateDirIfNotExists=1
    SiteDomain="order.foodcoop.nl"
    DirIcons="/admin/awstats/icon"
    AllowFullYearView=1
    LogFormat=1
    
  • For each host, create a corresponding configuration file:

    Include "/etc/awstats/awstats.conf"
    SiteDomain="order.foodcoop.nl"
    OnlyFiles="REGEX[democoop\/]"
    
  • Update cronjob in /etc/cron.d/awstats and replace user www-data with awstats.

  • Add Apache config in default-ssl

    Alias /admin/awstats/icon/ /usr/share/awstats/icon/
    Alias /admin/awstats/classes/ /usr/share/java/awstats/
    Alias /admin/awstats /var/cache/awstats
    <Location /admin/awstats>
            Options +Indexes
            DirectoryIndex index.html index.en.html
    </Location>
    

Mysql & Redis

  • apt-get install mysql-server redis-server

  • Set complex root password, create /root/.my.cnf (proper permissions!)

    [client]
    user = root
    password = very_complex_mysql_root_passwd
  • Install resque-web to monitor resque queues

    • Install using GIT

      cd /usr/local
      git clone https://github.com/wvengen/resque-web-passenger.git
      rm -f resque-web-passenger/.rvmrc
      addgroup --system resque-web
      adduser --system --home /usr/local/resque-web-passenger --disabled-password --disabled-login --ingroup resque-web resque-web
      adduser resque-web rvm
      chown resque-web:resque-web tmp
    • then, as normal user in same dir, run rvmsudo bundle install

    • add to apache config in /etc/apache2/sites-available/default-ssl:

      # resque-web
      Alias /admin/resque-web /usr/local/resque-web-passenger/public
      <Location /admin/resque-web>
              PassengerUser resque-web
              PassengerBaseURI /admin/resque-web
              PassengerAppRoot /usr/local/resque-web-passenger
      </Location>
      <Directory /usr/local/resque-web-passenger/public>
              Options -MultiViews
      </Directory>
      

Foodsoft deployment

  • Create a user foodsoft will run as, and a deployment user

    adduser --disabled-password --disabled-login --group foodsoft
    adduser --disabled-password foodsoft
    adduser deploy foodsoft
    mkdir -p /www/apps
    chmod -R g+ws /www
    chown -R root:deploy /www

    And setup the ssh authorized keys (e.g. see here).

  • Install dependencies for gems:

    apt-get install libmysqlclient-dev libcurl3-dev libxml2-dev libxslt-dev libffi-dev libreadline-dev
  • Allow deploy user to create new users and databases (for first-time setup)

    • create deploy sql user, store login in his ~/.my.cnf under [client]
    • grant sql grant and create to the deploy user
    • allow to sudo to foodsoft (for running resque), add this in /etc/sudoers.d/deploy
    deploy   ALL=(foodsoft) NOPASSWD: ALL
    
  • Apache config for a deployment:

    Alias /f /www/apps/foodsoft_main/current/public
    <Directory /www/apps/foodsoft_main/current/public>
      Options -MultiViews
    </Directory>
    <Location /f>
      PassengerBaseURI /f
      PassengerAppRoot /www/apps/foodsoft_main/current
      PassengerUser    foodsoft
      PassengerGroup   foodsoft
    </Location>
    
  • Log rotation. Create a file /etc/logrotate.d/railsapps

    # logrotate config for Rails apps deployed with Capistrano
    # http://stackoverflow.com/a/4883967
    /www/apps/*/shared/log/*.log {
      minsize 1M
      maxsize 100M
      weekly
      missingok
      maxage 365
      dateext
      compress
      delaycompress
      notifempty
      copytruncate
      su deploy deploy
    }
    

Backups

Currently there is no solid backup strategy. To have at least something, the following script is used to make a quick backup of all relevant data and configuration (only web statistics are missing).

DATE=`date +%Y%m%d`
DIR=./$DATE
HOST=order.foodcoop.nl

for db in `ssh ${HOST} cat /www/apps/*/current/config/{database,app_config}.yml \
	          | sed 's/#.*$//; s/^\s*database:\s*\(.\+\)\s*$/\1/p; d' \
	          | grep -v '_tmp\|_test\|_demo\|true' \
 	          | sort | uniq`; do
    ssh $HOST mysqldump $db | gzip -c >${DIR}/fcnl-$db.sql.gz;
done
for cfg in `ssh ${HOST} ls /www/apps/*/current/config/app_config.yml`; do
    app=`echo "$cfg" | sed 's/^\/www\/apps\/\([^\/]\+\)\/.*/\1/p;d'`;
    ssh ${HOST} cat $cfg | gzip -c >${DIR}/fcnl-$app.app_config.gz;
done