Home C++ Home Server
**My Perfect Home Server Setup** In this part of my blog you can find tutorials for setting up your home server. I wrote them down while working on my own server that serves as a substitute for the usual cloud services. New posts will be added to the bottom. The idea is to be able to follow the instructions from top to bottom and get a fully functional server at the end. Function | Software used ------------------------|---------------- Operating System | [Ubuntu server 18.04](https://ubuntu.com/download/server) Administration | [ISPConfig](https://www.ispconfig.org/), [Webmin](http://webmin.com) Web server | [nginx](https://www.nginx.com/) Mail server | [postfix](http://www.postfix.org), [dovecot](https://www.dovecot.org/) Webmail frontend | [roundcube](https://roundcube.net/) Location sharing | [Hauk](https://github.com/bilde2910/Hauk) Various cloud services | [NextCloud](https://nextcloud.com/) Project/Code hosting | [GitLab](https://gitlab.com/) [Table [Software]: Current server setup.] # Basic Setup For the basic setup I recommend to follow https://www.howtoforge.com/tutorial/perfect-server-ubuntu-18-04-nginx-bind-dovecot-and-ispconfig-3/. Be aware that you should make the server's fully-qualified domain name (FQDN) a subdomain of the main domain you want to use for your server, in the form of servername.yourdomain.tld. If you need some more information on the FQDN or want to change it after the basic setup follow https://gridscale.io/en/community/tutorials/hostname-fqdn-ubuntu/. Webmin is another very useful tool for your administrating needs. Making a lot of things that are too low-level for ISPConfig a lot easier. From updating the server to adding new users to a phpMyAdmin alternative (I didn't even install that one during the first tutorial. If your users need it you should still install it though). And I haven't even scratched the surface of the functionality of Webmin. To finish off the basic setup you should secure your mail server with a certificate. For that I recommend the following tutorial that uses Let's Encrypt to generate the certificates. Keep in mind to use the certificates of the (sub)domain you want to use as mail server later. https://www.howtoforge.com/tutorial/securing-ispconfig-3-with-a-free-lets-encrypt-ssl-certificate/ # Migrate ISPConfig from apache to nginx When I first started setting up my server I used apache instead of nginx. Later I learned that some things might be easier and faster with nginx, so I migrated the server. As this was not quite trivial with ISPConfig I wrote down what I did to get the server running smoothly again. First follow https://blog.schaal-24.de/ispconfig/ispconfig-apache-durch-nginx-ersetzen/?lang=en steps 1-4. Then stop and unregister apache ``` bash $ sudo /etc/init.d/apache2 stop $ sudo update-rc.d -f apache2 remove ``` Download ISPconfig again and execute the update script ``` bash $ cd /tmp $ wget -O ispconfig.tar.gz https://git.ispconfig.org/ispconfig/ispconfig3/repository/archive.tar.gz?ref=stable-3.1 $ tar xfz ispconfig.tar.gz $ cd ispconfig3*/install/ $ sudo php -q update.php ``` The default options should be exactly what you want in the update script. After that it should be safe to start nginx. Go back to your ISPConfig web-interface. To generate the vhost-files for nginx go through all domains and toggle the "active"-checkbox. # Install NextCloud on ISPConfig with nginx I followed the instructions on https://www.allerstorfer.at/install-nextcloud-15-on-ubuntu-18-04-with-ispconfig-31/ for the basic setup of NextCloud but without the Collabora parts. I don't need that. For NextCloud to work with nginx add the following nginx-directives in the Options-tab on your respective domain (you need to be the ISPConfig admin user to access that tab): ``` # Add headers to serve security related headers add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; add_header Strict-Transport-Security "max-age=31536000" always; # set max upload size client_max_body_size 512M; fastcgi_buffers 64 4K; # Enable gzip but do not remove ETag headers gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; location / { location = /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; } location = /.well-known/caldav { return 301 $scheme://$host/remote.php/dav; } location ~ /.well-known/acme-challenge { allow all; } location / { rewrite ^ /index.php$uri; } location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { deny all; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; } location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34])\.php(?:$|/) { include fastcgi_params; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; #Avoid sending the security headers twice fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; fastcgi_pass unix:/var/lib/php7.2-fpm/web4.sock; fastcgi_intercept_errors on; fastcgi_request_buffering off; } location ~ ^/(?:updater|ocs-provider)(?:$|/) { try_files $uri/ =404; index index.php; } # Make sure it is BELOW the PHP block location ~* \.(?:css|js)$ { try_files $uri /index.php$uri$is_args$args; add_header Cache-Control "public, max-age=7200"; # Add headers to serve security related headers (It is intended to # have those duplicated to the ones above) add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; # Optional: Don't log access to assets access_log off; } location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ { try_files $uri /index.php$uri$is_args$args; # Optional: Don't log access to other assets access_log off; } } ``` Don't forget to change the line with `fastcgi_pass` to contain the correct socket for the linux user of this domain. Then go to the `Redirect` tab and make sure the checkbox `Rewrite HTTP to HTTPS` is checked. For the curious: the weird outside `location / { ... }` is necessary because of how ISPConfig overrides our php location directive. See https://help.nextcloud.com/t/nextcloud-16-0-4-not-enough-free-space/59976/7 for more information. # Install GitLab on ISPConfig with nginx Add GitLab repository with the curl command. ``` bash $ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash ``` Then install GitLab CE Community Edition with the apt command. ~~~~~~ bash $ sudo apt install gitlab-ce -y ~~~~~~ You'll see something like this when the installer is finished. ![terminal output of the gitlab installer](gitlab_installed.png "Terminal output") Now go to your ISPConfig panel and create a new website with domain `gitlab.yourdomain.tld`. Also add let's encrypt ssl certificates. Don't forget to add a CNAME entry at your DNS provider or in your server. Next, we will generate the DHPARAM certificate using the OpenSSL command. Create a new directory `/etc/gitlab/ssl` and run the OpenSSL command below. ``` bash $ sudo mkdir -p /etc/gitlab/ssl/ $ sudo openssl dhparam -out /etc/gitlab/ssl/dhparams.pem 2048 ``` Now change the permission of the SSL directory. ``` bash $ sudo chmod 600 /etc/gitlab/ssl/* ``` Now edit the gitlab config and set the correct domain name. ``` bash $ sudo nano /etc/gitlab/gitlab.rb ``` Change the 'external_url' value with your own domain name. ``` external_url 'https://gitlab.yourdomain.tld' ``` (make sure you get the *s* in `https`) Now we want to disable the nginx server that is bundled with gitlab as we want to use our own. Find (ctrl+w in nano) the `nginx['enable']` config setting and set it to false. ``` nginx['enable'] = false ``` Change port used by gitlab unicorn as the default is port 8080 which interferes with ISPConfig: ``` unicorn['port'] = 8081 ``` Next we also need to set the user and group that was assigned to the website by ISPConfig. So find `web_server['external_users']` and `web_server['group']` and insert the correct user and group (you can find that in the web domain configuration in ISPConfig. It's the last parts of the Document Root, for example `/var/www/clients/client1/web9`) ``` web_server['external_users'] = ['web9'] web_server['group'] = 'client1' ``` Save and exit. Now run the 'gitlab-ctl' command below. ``` bash $ sudo gitlab-ctl reconfigure ``` This command will install and configure GitLab based on the `/etc/gitlab/gitlab.rb` configuration file. Now we have to link GitLab's web directory to the web directory ISPConfig created for us. ``` bash $ sudo ln -s /opt/gitlab/embedded/service/gitlab-rails/public/ /var/www/gitlab.yourdomain.tld/web/public $ sudo chown -R web9:client1 /var/www/gitlab.yourdomain.tld/web/public/ ``` Next go to the web domain configuration site for gitlab.yourdomain.tld in ISPConfig. In the `Domain` tab deactivate `Own Error-Documents`. In the `Redirect` tab activate the box `Rewrite HTTP to HTTPS`. Then go to `Options` tab (you might need to be the admin user to see that one) and paste the following block into `nginx Directives`: ``` server_tokens off; ## Don't show the Nginx version number, a security best practice ##subroot public ## # GitLab needs backward compatible ciphers to retain compatibility with Java IDEs ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 5m; disable_symlinks off; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; location / { client_max_body_size 0; gzip off; ## https://github.com/gitlabhq/gitlabhq/issues/694 ## Some requests take more than 30 seconds. proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Ssl on; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://gitlab-workhorse; } } upstream gitlab-workhorse { server unix:/var/opt/gitlab/gitlab-workhorse/socket fail_timeout=100; ``` (yes, we have to do a little ugly hack there at the end to get the gitlab-workhorse to work with the way ISPConfig inserts the directives into the .vhost files.) Now click save and wait for the config to be generated and nginx restarted. Once that is done your brand new gitlab instance should be available at https://gitlab.yourdomain.tld ! Credits: * https://www.howtoforge.com/tutorial/how-to-install-and-configure-gitlab-on-ubuntu-1804/ * https://docs.gitlab.com/omnibus/settings/nginx.html * https://git.ispconfig.org/ispconfig/ispconfig3/merge_requests/698