Skip to content

Instantly share code, notes, and snippets.

@jcohlmeyer
Last active August 15, 2018 23:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcohlmeyer/c8230472356ec7a78b39361a4dcac342 to your computer and use it in GitHub Desktop.
Save jcohlmeyer/c8230472356ec7a78b39361a4dcac342 to your computer and use it in GitHub Desktop.
Statamic DO

SSH config (on your local machine)

Host [name]
  HostName [floating_ip]
  User root
  IdentityFile ~/.ssh/[ssh_key]
  IdentitiesOnly yes

Update software

  • Note you may have to reboot before updating.
ssh [name]
apt update
apt upgrade
reboot

Add user

ssh [name]
adduser [username]
usermod -aG sudo [username]
usermod -aG www-data [username]

Install the key on the server

cat ~/.ssh/authorized_keys
cd /home/[username]/
su [username]
mkdir .ssh
chmod 700 .ssh
nano .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
exit
exit

Edit your local ssh config

...
  User [username]
  ...

Disable Password Auth

ssh [name]
sudo nano /etc/ssh/sshd_config

Change Settings

PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PermitRootLogin no

Restart SSH

sudo systemctl reload sshd

Test Changes

  • Edit ssh config to use root again
  • Connect & make sure you get permission denied
  • Change ssh config back to use [username]

Firewall Setup

ssh [name]
sudo ufw app list
sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
sudo ufw status

Instal NGINX

sudo apt install nginx

Install Mira DB

sudo apt install mariadb-server mariadb-client
sudo mysql_secure_installation
  • Enter current password for root (enter for none): <-- press enter
  • Set root password? [Y/n] <-- y
  • New password: <-- Enter the new MariaDB root password here
  • Re-enter new password: <-- Repeat the password
  • Remove anonymous users? [Y/n] <-- y
  • Disallow root login remotely? [Y/n] <-- y
  • Reload privilege tables now? [Y/n] <-- y
sudo mysql -u root -p

Install PHP 7.1-fpm

sudo apt install python-software-properties
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.1-fpm

Configure PHP

sudo nano /etc/php/7.1/fpm/php.ini
  • change cgi.fix_pathinfo=1 to cgi.fix_pathinfo=0
sudo systemctl reload php7.1-fpm

Search for & Install PHP Modules

sudo apt-cache search php7.1

Install php modules

sudo apt install php7.1-curl php7.1-gd php7.1-mbstring php7.1-mcrypt php7.1-xml php7.1-zip mcrypt libgd-tools

If MySQL is required

sudo apt install php7.1-mysql

Install PHP My Admin

sudo apt install phpmyadmin
  • Web server to configure automatically: <-- Select nothing
  • Configure database for phpmyadmin with dbconfig-common? <-- No
sudo mysql -u root
CREATE USER '[user]'@'localhost' IDENTIFIED BY '[password]';
GRANT ALL PRIVILEGES ON *.* TO '[user]'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
exit

Set Up Automatic Security Updates

sudo dpkg-reconfigure --priority=low unattended-upgrades

Set Up Let's Encrypt Client

Install

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx

Set Up the SSL Cert

sudo certbot --nginx -d [example.com] -d [www.example.com]

Test at: (SSL Labs)[https://www.ssllabs.com/ssltest/]

Set Up Auto Renewal

sudo crontab -e

Add:

. . .
15 3 * * * /usr/bin/certbot renew --quiet

Make a Unique Diffie Hellman Key

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Make ssl.conf

sudo nano /etc/nginx/ssl.conf
# SSL/TLS configuration, with TLSv1.0 disabled because it is insecure; note that IE 8, 9 & 10 support
# TLSv1.1, but it's not enabled by default clients using those browsers will not be able to connect
ssl_protocols TLSv1.2 TLSv1.1;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5';
ssl_buffer_size 4k;
ssl_session_timeout 4h;
ssl_session_cache shared:SSL:40m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem;

# Security headers via https://securityheaders.io
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "no-referrer-when-downgrade";

# Add Content-Security-Policy HTTP response header. Helps reduce XSS risks on
# modern browsers by declaring what dynamic resources are allowed to load via a
# HTTP Header.  See https://content-security-policy.com/
# Uncomment this only if you know what you're doing; it will need tweaking
# add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always;

Install the Let's Encrypt Cert

sudo mkdir /etc/nginx/ssl
sudo nano /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem 
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----

Edit the NGINX Config

sudo nano /etc/nginx-sites-available/default
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#

# Expires map
map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   max;
    application/javascript     max;
    ~image/                    max;
}


server {
    listen 80 default_server;
    listen [::]:80 default_server;

    expires 365d;

    server_name example.com www.example.com;
    root /var/www/html;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    expires 365d;

    server_name www.example.com;
    root /var/www/html;

    include snippets/ssl.conf;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    expires $expires;

    server_name example.com;
    root /var/www/html;

    index index.html index.htm index.php;

    location / {
        try_files /static${uri}_${query_string}.html $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/example.com.error.log error;

    error_page 404 /index.php;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
	      # With php7.0-cgi alone:
        # fastcgi_pass 127.0.0.1:9000;
        # With php7.1-fpm:
        fastcgi_pass unix:/run/php/php7.1-fpm.sock;
    }

    # Block access to hidden files (except the /.well-known/ dir)
    location ~ /(?!.well-known)(\.)\w+ {
        deny all;
    }

    # Block access to content/data files
    location ~* /(.*)\.(?:md|yaml|textile)$ {
        deny all;
        return 404;
    }

    # Block access to the Statamic app
    location ^~ /statamic {
        deny all;
        return 404;
    }

    # Enable gzip compression
    gzip on;
    gzip_min_length  1100;
    gzip_buffers  4 32k;
    gzip_types    text/plain application/x-javascript text/xml text/css;
    gzip_vary on;

    # File Upload Size
    client_max_body_size 8M;

    include snippets/ssl.conf;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment