**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.

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