For this blog, i’ve setup a linux KVM vps, using as distro Fedora 27. Fedora 27 comes with Selinux enforced security policy by default this is OK for system or apps where you required a high security level, but for my case to serve a static blog and run a couple of services like OpenSSH and Nginx is ok to set the security policy on permissive mode.
changing the policy can be done via command or setup in permanent way on the selinux config
in /etc/selinux/config
set selinux in permissive mode from the command line:
sudo setenforce=0
# to verify the security policy mode
getenforce
like this on /etc/selinux/config
:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
for Nginx we define a config like this initially:
server {
listen 80;
listen [::]:80;
server_name rz0r.net www.rz0r.net;
root /srv/www;
location / {
index index.html;
autoindex off;
}
}
we are going to use the directory /srv/www/
to server the blog files and also define in the hosts file the alias for this domain
# /etc/hosts
<IP address> rz0r.net www.rz0r.net
for the firewall we use firewalld
# check the firewall service status
sudo systemctl status firewalld
# enable firewall service if it's no active
sudo systemctl enable firewalld
# add services and ports,
# if openssh is not enable can be added in the same way
sudo firewall-cmd --zone=public --permanent --add-service=https
sudo firewall-cmd --zone=public --permanent --add-service=http
sudo firewall-cmd --zone=public --permanent --add-port 443/tcp
sudo firewall-cmd --zone=public --permanent --add-port 80/tcp
# verify the firewall rules
sudo firewall-cmd --state
# verify the enable services
sudo firewall-cmd --zone=public --list-services
for OpenSSH it needs to be setup to allow only public key authentication
the relevant option to add to /etc/ssh/sshd_config
are
PasswordAuthentication no
PubkeyAuthentication yes
hugo can be found on the fedora packages and can be installed like this in the local machine
sudo dnf install hugo
now we build the blog using hugo
command on the local machine and rsync to upload the files to the server:
# on the blog directory
hugo -v && rsync -avz --delete public/ root@vps:/srv/www/
this could be automated using a script like this:
#!/usr/bin/bash
# deploy.sh
DEST="/srv/www/"
SERVER_USERNAME="your username"
SERVER_HOSTNAME="your server ip or hostname"
hugo -v && \
rsync -avz --delete public/ ${SERVER_USERNAME}@${SERVER_HOSTNAME}:${DEST}
# Blog files
archetypes
config.toml
content
deploy.sh
public
static
themes
Next step is create a SSL certificate using LetsEncrypt, LetsEncrypt is available on Fedora we only need install the package and run with the params to generate the certificate for the domain and pass the verification.
sudo dnf install letsencrypt
sudo letsencrypt --text --email [email protected] \
--domains www.example.com,example.com,foo.example.com \
--agree-tos --renew-by-default --manual certonly
once the certificate has been generated is ready to use on /etc/letsencrypt/live/
the last step is update the Nginx configuration to use the new certificate
server {
listen 80;
listen [::]:80;
access_log off;
error_log off;
server_name rz0r.net www.rz0r.net;
return 301 https://$server_name/$request_uri;
}
server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl;
server_name rz0r.net www.rz0r.net;
client_max_body_size 20M;
root /srv/www;
ssl_certificate /etc/letsencrypt/live/rz0r.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rz0r.net/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
#ssl_trusted_certificate /etc/ssl/private/ca-certs.pem;
ssl_trusted_certificate /etc/letsencrypt/live/rz0r.net/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location / {
index index.html;
autoindex off;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 8d;
}
error_page 404 /404.html;
location = /40x.html {}
}
bonus: to renew automatically the certificate with letsencrypt we can use a cronb job like this:
# checking every monday at 2:30 if the certificate needs to be renewed.
# then 5 min later restart nginx
30 2 * * 1 /bin/certbot renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl restart nginx
References: