Setting up home server¶
Setup static IP/disable Wifi¶
Download Ubuntu Server Get Ubuntu Server | Download | Ubuntu
Allow laptop to continue running with lid closed:
sudo vi /etc/systemd/logind.conf
Add (remove comment):
HandleLidSwitch=ignore
HandleLidSwitchDocked=ignore
Restart daemon:
sudo systemctl restart systemd-logind.service
find name of lan port:
ip a
edit network interfaces (there is a default in that folder, edit that):
sudo vi /etc/netplan/50-cloud-init.yaml
add:
network:
version: 2
renderer: networkd
ethernets:
enp2s0f0:
addresses: [192.168.1.50/24]
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
apply policy:
sudo netplan generate
sudo netplan apply
Install docker + home assisstant¶
Make service folder structure:
sudo mkdir -p /srv/homeassistant/{compose,config,data,logs,secrets}
sudo chown -R $USER:$USER /srv/homeassistant
Create docker compose:
sudo vi /srv/homeassistant/compose/docker-compose.yml
Paste:
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host # Needed for mDNS/SSDP/Bluetooth
privileged: true
volumes:
- ../config:/config
- ../data/ha:/data
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
# Example USB adapter (Zigbee/Z-Wave/RCP):
# - /dev/serial/by-id/...:/dev/ttyUSB0
environment:
- TZ=Africa/Johannesburg
matter-server:
image: ghcr.io/home-assistant-libs/python-matter-server:stable
container_name: matter-server
restart: unless-stopped
network_mode: host
volumes:
- ../data/matter:/data
environment:
- MATTER_SERVER_STORAGE=/data
- TZ=Africa/Johannesburg
Configure HA conf and add following (only accessible on local host)
sudo vi /srv/homeassistant/config/configuration.yaml
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1 # host nginx on the same box
- ::1 # IPv6 loopback (optional but harmless)
Create nginx server to forward to HA over port 80:
sudo vi /etc/nginx/sites-available/homeassistant.conf
server {
listen 80;
server_name ha.example.com;
location / {
proxy_pass http://127.0.0.1:8123;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
}
Enable + certbot:
sudo ln -s /etc/nginx/sites-available/homeassistant.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d home.cliftonbartholomew.co.za
Start homeassistant:
cd /srv/homeassistant/compose
sudo docker compose up -d
Install openproject¶
Make service folder:
sudo mkdir -p /srv/openproject/{compose,config,data,logs,secrets}
sudo chown -R $USER:$USER /srv/openproject
```
Create .env:
```bash
sudo vi /srv/openproject/compose/.env
Paste:
# ---- App ----
APP_DOMAIN=projects.cliftonbartholomew.co.za
APP_PORT=8085 # host loopback port for nginx to hit
# ---- Postgres ----
POSTGRES_DB=openproject
POSTGRES_USER=openproject
POSTGRES_PASSWORD=aR31DovcdmvSml96Rh1g9t5KGMAFXCIGi0DYw8MwCgolf
POSTGRES_VERSION=17
# ---- Email (optional: set when you wire SMTP) ----
# EMAIL__DELIVERY__METHOD=smtp
# EMAIL__SMTP__ADDRESS=smtp.yourhost.com
# EMAIL__SMTP__PORT=587
# EMAIL__SMTP__DOMAIN=example.com
# EMAIL__SMTP__AUTHENTICATION=login
# EMAIL__SMTP__ENABLE__STARTTLS__AUTO=true
# EMAIL__SMTP__USER__NAME=postmaster@example.com
# EMAIL__SMTP__PASSWORD=yourpassword
Create docker compose:
sudo vi /srv/openproject/compose/docker-compose.yml
Paste:
networks:
web:
external: true # shared reverse-proxy network (create it if you don’t already have it)
default:
name: openproject_internal
services:
postgres:
image: postgres:${POSTGRES_VERSION}
container_name: openproject_postgres
restart: unless-stopped
env_file:
- .env
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ../data/pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
memcached:
image: memcached:1.6-alpine
container_name: openproject_memcached
restart: unless-stopped
command: ["memcached", "-m", "128", "-I", "5m"] # 128MB cache, 5MB max item size
healthcheck:
test: ["CMD", "sh", "-c", "printf 'stats\n' | nc 127.0.0.1 11211 | grep -q 'STAT'"]
interval: 30s
timeout: 5s
retries: 5
openproject:
image: openproject/openproject:16.4.0
container_name: openproject_app
depends_on:
postgres:
condition: service_healthy
memcached:
condition: service_started
restart: unless-stopped
env_file:
- .env
environment:
# --- Core connectivity ---
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
OPENPROJECT_HOST__NAME: ${APP_DOMAIN}
OPENPROJECT_HTTPS: "true" # TLS terminated at host nginx
OPENPROJECT_PORT: "80"
# --- Cache (memcached) ---
CACHE__STORE__MEMCACHE__SERVERS: "memcached:11211"
# --- Email (uncomment if set in .env) ---
# EMAIL__DELIVERY__METHOD: ${EMAIL__DELIVERY__METHOD}
# EMAIL__SMTP__ADDRESS: ${EMAIL__SMTP__ADDRESS}
# EMAIL__SMTP__PORT: ${EMAIL__SMTP__PORT}
# EMAIL__SMTP__DOMAIN: ${EMAIL__SMTP__DOMAIN}
# EMAIL__SMTP__AUTHENTICATION: ${EMAIL__SMTP__AUTHENTICATION}
# EMAIL__SMTP__ENABLE__STARTTLS__AUTO: ${EMAIL__SMTP__ENABLE__STARTTLS__AUTO}
# EMAIL__SMTP__USER__NAME: ${EMAIL__SMTP__USER__NAME}
# EMAIL__SMTP__PASSWORD: ${EMAIL__SMTP__PASSWORD}
# --- Optional: force locale/timezone ---
# OPENPROJECT_DEFAULT__LOCALE: en_ZA
# OPENPROJECT_DEFAULT__TIMEZONE: Africa/Johannesburg
volumes:
- ../data/assets:/var/openproject/assets # attachments, repos, etc.
- ../logs/openproject:/var/log/supervisor # container logs (optional)
ports:
- "127.0.0.1:${APP_PORT}:80"
networks:
- default
- web
Create docker network:
sudo docker network create web || true
Create nginx conf:
sudo vi /etc/nginx/sites-available/openproject.conf
Paste:
server {
server_name projects.cliftonbartholomew.co.za
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8085;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# WebSocket support (simplified)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Link + certbot:
sudo ln -s /etc/nginx/sites-available/openproject.conf /etc/nginx/sites-enabled/openproject.conf
sudo nginx -t && sudo systemctl reload nginx
# Let’s Encrypt (will convert to HTTPS config automatically)
sudo certbot --nginx -d projects.cliftonbartholomew.co.za
Start openproject:
cd /srv/openproject/compose
sudo docker compose up -d