A comprehensive home server setup using Docker, designed for running self-hosted services with security and ease of management in mind.
AtHome provides a ready-to-deploy home server infrastructure with:
- 🔒 Secure reverse proxy (Traefik)
- 🎯 Network-wide ad blocking (Pi-hole)
- 🐳 Container management UI (Portainer)
- 🔐 Automated SSL certificate management
- 🌐 Custom local domain (.at.home)
- Security First: Hardened SSH configuration, UFW firewall setup, and SSL encryption
- Easy Management: Web-based container management through Portainer
- Ad Blocking: Network-wide ad blocking and custom DNS management with Pi-Hole
- Automated: Certificate renewal and container updates
- Customizable: Easy to extend with additional services
- Ubuntu Server v20.04.3
- Docker v20.10.12
- Docker Compose v2.2.3
- Traefik v2.6.0
- Portainer CE v2.11.1
Hardware: Asus Chromebox 3 Firmware: MrChromebox.tech Operating System: Ubuntu Server 20.04.3 Networking: Ethernet Admin User: mislam SSH Login Key: ed25519.pub
- Router: router.at.home
- Traefik: traefik.at.home
- Portainer: portainer.at.home
sudo apt update && sudo apt upgrade -y
Make sure you are using ethernet interface with static IP address:
sudo nano /etc/netplan/00-installer-config.yaml
It should look this:
network:
ethernets:
eno0:
addresses:
- 192.168.0.253/24
gateway4: 192.168.0.254
nameservers:
addresses:
- 1.1.1.1
version: 2
Now reboot:
sudo reboot
Set the defaults to deny incoming and allow outgoing connections.
sudo ufw default deny incoming
sudo ufw default allow outgoing
SSH into the server and edit the SSH config:
sudo nano /etc/ssh/sshd_config
Add the following line above #Port 22
:
Protocol 2
Change the following lines as follows:
Port XXXX
PermitRootLogin no
MaxAuthTries 3
PasswordAuthentication no
PermitEmptyPasswords no
ClientAliveInterval 300
Replace XXXX
with a port number that is hard to guess.
And add the following line after #MaxSessions
:
AllowUsers mislam
Save and exit the config file, and restart the SSH server:
sudo service sshd reload
Finally set UFW to allow the SSH port:
sudo ufw allow 9022
Disable automatic spawning of virtual terminals:
sudo nnao /etc/systemd/logind.conf
Change the followings:
NAutoVTs=0
ReserveVT=0
Disable [email protected]
and reboot:
systemctl disable [email protected]
sudo reboot
Next time the server boots, it will no longer prompt for login.
sudo apt install ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io -y
By default, only root and user with sudo privileges can execute Docker commands. To execute Docker commands as non-root user, add your user to the docker group:
sudo usermod -aG docker $USER
Download and install the latest release from GitHub:
mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose
git clone https://gitlab.com/mislam/athome.git ~/.athome && cd $_
Generate new root CA and server certificate:
bin/mkcert -new
It will generate a root CA (for 100 years) and server certificate (for 31 days) and sets a cron job to renew the server certificate every month.
Run the following command from a Mac to download the CA certificate, and add it to Mac's keychain:
scp server_hostname:~/.athome/certs/ca.crt . && sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.crt && rm ca.crt
Note: Here server_hostname
is the hostname of the server machine. And we assume that there is a SSH config file on the Mac at ~/.ssh/config
with the following lines:
Host server_hostname
Hostname xxx.xxx.x.x
Port xxxx
User server_admin_username
IdentityFile ~/.ssh/id_ed25519
If you want to delete the certificate from the keychain, simply run:
sudo security delete-certificate -c "AtHome CA" /Library/Keychains/System.keychain
Install htpasswd
:
sudo apt install apache2-utils
You will not be able to write your password as it is, you first need to generate a hash of your password:
sed -i s#USER:PASSWORD#$(htpasswd -nbB MYUSER MYPASSWORD)# config/traefik/dynamic.yml
Replace MYUSER
and MYPASSWORD
with your own credentials you would like to use for Traefik Dashboard. This sed
command will replace USER:PASSWORD
in the dynamic.yml
file with something like this:
USER:$apr1$GTSSKUUa$K1XULJfw9tbdikiJPBpQm1
Ubuntu includes systemd-resolved
which is configured by default to implement a caching DNS stub resolver. This will prevent pi-hole from listening on port 53. The stub resolver should be disabled with:
sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf
This will not change the nameserver settings, which point to the stub resolver thus preventing DNS resolution. Change the /etc/resolv.conf
symlink to point to /run/systemd/resolve/resolv.conf
, which is automatically updated to follow the system's netplan
:
sudo sh -c 'rm /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'
After making these changes, you should restart systemd-resolved
:
sudo systemctl restart systemd-resolved
Run:
docker compose up -d
Change Pi-Hole login password:
docker exec -d pihole pihole -a -p MY_PIHOLE_PASSWD
Login to the Pi-Hole Web UI and add the following two domains to the blacklist:
sonx.mediasearch.verizon.com
and
(\.|^)(youtube|googlevideo|ytimg|youtube-ui\.l\.google|ytimg\.l\.google|ytstatic\.l\.google|youtubei\.googleapis)\.com$
Find all listening TCP ports:
sudo lsof -nP -iTCP -sTCP:LISTEN
After running docker compose up
, if you need to make changes in the docker-compose.yml
, make sure to run docker compose down
before make any change to the YML file. Otherwise it will cause unpredictable issues and headaches.
IP Subnet Calculator:
How to generate SSL certificate:
- https://examples.openshift.pub/certificate/
- https://www.golinuxcloud.com/shell-script-to-generate-certificate-openssl/
DNS over HTTPS:
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
This project is provided as-is. Please ensure you understand the security implications of running these services on your network.