449 lines
9.3 KiB
Markdown
449 lines
9.3 KiB
Markdown
# Stappenplan: Umami op Hostinger VPS
|
||
|
||
**Omgeving:** Ubuntu 24.04 LTS · 8 GB RAM · 2 vCPU · 100 GB SSD
|
||
**Doel:** Umami analytics bereikbaar op `analytics.iso27diy.com`
|
||
|
||
---
|
||
|
||
## Overzicht
|
||
|
||
1. Server beveiligen (gebruiker, firewall, SSH)
|
||
2. Docker installeren
|
||
3. Subdomein aanmaken in Netlify DNS
|
||
4. Umami deployen met Docker Compose
|
||
5. Nginx instellen als reverse proxy
|
||
6. SSL certificaat installeren (Let's Encrypt)
|
||
7. Tracking script toevoegen aan Netlify site
|
||
8. UTM-tracking testen
|
||
|
||
Geschatte tijd: **45–60 minuten**
|
||
|
||
---
|
||
|
||
## Stap 1 — Server beveiligen
|
||
|
||
### 1.1 Inloggen als root
|
||
|
||
```bash
|
||
ssh root@<jouw-server-ip>
|
||
```
|
||
|
||
### 1.2 Systeem updaten
|
||
|
||
```bash
|
||
apt update && apt upgrade -y
|
||
```
|
||
|
||
### 1.3 Nieuwe gebruiker aanmaken
|
||
|
||
Werken als root is risicovol. Maak een aparte gebruiker aan:
|
||
|
||
```bash
|
||
adduser deploy
|
||
usermod -aG sudo deploy
|
||
```
|
||
|
||
Kies een sterk wachtwoord wanneer daarom gevraagd wordt.
|
||
|
||
### 1.4 SSH-toegang instellen voor nieuwe gebruiker
|
||
|
||
```bash
|
||
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
|
||
```
|
||
|
||
Test in een **nieuw terminalvenster** (sluit de huidige sessie nog niet):
|
||
|
||
```bash
|
||
ssh deploy@<jouw-server-ip>
|
||
```
|
||
|
||
Als dat werkt: goed. Sluit nu de root-sessie.
|
||
|
||
### 1.5 Root-login via SSH uitschakelen
|
||
|
||
```bash
|
||
sudo nano /etc/ssh/sshd_config
|
||
```
|
||
|
||
Zoek de regel `PermitRootLogin yes` en verander die naar:
|
||
|
||
```
|
||
PermitRootLogin no
|
||
```
|
||
|
||
Sla op met `Ctrl+O`, sluit met `Ctrl+X`. Herstart SSH:
|
||
|
||
```bash
|
||
sudo systemctl restart ssh
|
||
```
|
||
|
||
### 1.6 Firewall instellen
|
||
|
||
```bash
|
||
sudo ufw allow OpenSSH
|
||
sudo ufw allow 80/tcp
|
||
sudo ufw allow 443/tcp
|
||
sudo ufw enable
|
||
```
|
||
|
||
Controleer de status:
|
||
|
||
```bash
|
||
sudo ufw status
|
||
```
|
||
|
||
Je zou dit moeten zien:
|
||
|
||
```
|
||
Status: active
|
||
To Action From
|
||
-- ------ ----
|
||
OpenSSH ALLOW Anywhere
|
||
80/tcp ALLOW Anywhere
|
||
443/tcp ALLOW Anywhere
|
||
```
|
||
|
||
|
||
### 1.7 fail2ban installeren
|
||
|
||
```bash
|
||
sudo apt install -y fail2ban
|
||
```
|
||
|
||
Maak een configuratiebestand aan:
|
||
|
||
```bash
|
||
sudo nano /etc/fail2ban/jail.local
|
||
```
|
||
|
||
Plak:
|
||
|
||
```ini
|
||
[DEFAULT]
|
||
bantime = 1h
|
||
findtime = 10m
|
||
maxretry = 5
|
||
|
||
[sshd]
|
||
enabled = true
|
||
port = ssh
|
||
logpath = %(sshd_log)s
|
||
backend = %(sshd_backend)s
|
||
```
|
||
|
||
Activeer en start:
|
||
|
||
```bash
|
||
sudo systemctl enable fail2ban
|
||
sudo systemctl start fail2ban
|
||
```
|
||
|
||
Status controleren:
|
||
|
||
```bash
|
||
sudo fail2ban-client status sshd
|
||
```
|
||
|
||
Een gebanned IP handmatig deblokkeren:
|
||
|
||
```bash
|
||
sudo fail2ban-client set sshd unbanip <ip-adres>
|
||
```
|
||
|
||
---
|
||
|
||
## Stap 2 — Docker installeren
|
||
|
||
```bash
|
||
sudo apt install -y ca-certificates curl gnupg
|
||
sudo install -m 0755 -d /etc/apt/keyrings
|
||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
|
||
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||
echo \
|
||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
sudo apt update
|
||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||
```
|
||
|
||
Voeg je gebruiker toe aan de docker-groep (zodat je geen `sudo` nodig hebt):
|
||
|
||
```bash
|
||
sudo usermod -aG docker deploy
|
||
newgrp docker
|
||
```
|
||
|
||
Test of het werkt:
|
||
|
||
```bash
|
||
docker run hello-world
|
||
```
|
||
|
||
---
|
||
## Stap 3 — Subdomein aanmaken in Netlify DNS
|
||
|
||
Je domein `iso27diy.com` gebruikt Netlify als DNS. Zo voeg je het subdomein toe:
|
||
|
||
1. Log in op [app.netlify.com](https://app.netlify.com)
|
||
2. Ga naar **Domains** (linksboven in het menu)
|
||
3. Klik op `iso27diy.com`
|
||
4. Klik op **Add new record**
|
||
5. Vul in:
|
||
- **Type:** `A`
|
||
- **Name:** `analytics`
|
||
- **Value:** `<jouw-server-ip>` (het IP-adres van je Hostinger VPS)
|
||
- **TTL:** laat op standaard staan
|
||
1. Klik **Save**
|
||
|
||
Het DNS-record propageert doorgaans binnen 5–15 minuten. Je kunt het controleren via:
|
||
|
||
```bash
|
||
dig analytics.iso27diy.com
|
||
```
|
||
|
||
Wacht met de volgende stap tot het IP-adres correct terugkomt.
|
||
|
||
---
|
||
|
||
## Stap 4 — Umami deployen met Docker Compose
|
||
|
||
### 4.1 Map aanmaken
|
||
|
||
```bash
|
||
mkdir -p ~/umami && cd ~/umami
|
||
```
|
||
|
||
### 4.2 docker-compose.yml aanmaken
|
||
|
||
```bash
|
||
nano docker-compose.yml
|
||
```
|
||
|
||
Plak de volgende inhoud:
|
||
|
||
```yaml
|
||
version: '3'
|
||
|
||
services:
|
||
umami:
|
||
image: ghcr.io/umami-software/umami:postgresql-latest
|
||
ports:
|
||
- "127.0.0.1:3000:3000"
|
||
environment:
|
||
DATABASE_URL: postgresql://umami:umami_password@db:5432/umami
|
||
DATABASE_TYPE: postgresql
|
||
APP_SECRET: vervang_dit_door_een_willekeurige_lange_string
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
restart: always
|
||
|
||
db:
|
||
image: postgres:15-alpine
|
||
environment:
|
||
POSTGRES_DB: umami
|
||
POSTGRES_USER: umami
|
||
POSTGRES_PASSWORD: umami_password
|
||
volumes:
|
||
- umami-db:/var/lib/postgresql/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U umami"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 5
|
||
restart: always
|
||
|
||
volumes:
|
||
umami-db:
|
||
```
|
||
|
||
**Belangrijk:** vervang `umami_password` door een sterk wachtwoord, en `vervang_dit_door_een_willekeurige_lange_string` door een willekeurige string (bijv. via `openssl rand -base64 32`).
|
||
|
||
Genereer een willekeurige APP_SECRET:
|
||
|
||
```bash
|
||
openssl rand -base64 32
|
||
```
|
||
|
||
Kopieer de output en plak die als waarde voor `APP_SECRET`.
|
||
|
||
Sla op met `Ctrl+O`, sluit met `Ctrl+X`.
|
||
|
||
### 4.3 Umami starten
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
Controleer of de containers draaien:
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
Beide services (`umami` en `db`) moeten de status `running` hebben. Dit kan 1–2 minuten duren bij de eerste start.
|
||
|
||
Controleer de logs als iets niet klopt:
|
||
|
||
```bash
|
||
docker compose logs -f
|
||
```
|
||
|
||
---
|
||
|
||
## Stap 5 — Nginx instellen als reverse proxy
|
||
|
||
Nginx ontvangt het verkeer op poort 80/443 en stuurt het door naar Umami op poort 3000.
|
||
|
||
### 5.1 Nginx installeren
|
||
|
||
```bash
|
||
sudo apt install -y nginx
|
||
```
|
||
|
||
### 5.2 Configuratie aanmaken
|
||
|
||
```bash
|
||
sudo nano /etc/nginx/sites-available/analytics.iso27diy.com
|
||
```
|
||
|
||
Plak:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name analytics.iso27diy.com;
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection 'upgrade';
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_cache_bypass $http_upgrade;
|
||
}
|
||
}
|
||
```
|
||
|
||
Sla op en sluit.
|
||
|
||
### 5.3 Configuratie activeren
|
||
|
||
```bash
|
||
sudo ln -s /etc/nginx/sites-available/analytics.iso27diy.com \
|
||
/etc/nginx/sites-enabled/
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
```
|
||
|
||
`nginx -t` moet `syntax is ok` teruggeven.
|
||
|
||
---
|
||
|
||
## Stap 6 — SSL certificaat installeren
|
||
|
||
```bash
|
||
sudo apt install -y certbot python3-certbot-nginx
|
||
sudo certbot --nginx -d analytics.iso27diy.com
|
||
```
|
||
|
||
Certbot vraagt om een e-mailadres en of je akkoord gaat met de voorwaarden. Na afloop past het de Nginx-configuratie automatisch aan voor HTTPS en regelt het automatische verlenging.
|
||
|
||
Controleer automatische verlenging:
|
||
|
||
```bash
|
||
sudo certbot renew --dry-run
|
||
```
|
||
|
||
---
|
||
## Stap 7 — Eerste login en wachtwoord wijzigen
|
||
|
||
Ga naar `https://analytics.iso27diy.com` in je browser.
|
||
|
||
- **Gebruikersnaam:** `admin`
|
||
- **Wachtwoord:** `umami`
|
||
|
||
Ga direct naar **Settings → Profile** en stel een sterk wachtwoord in.
|
||
|
||
|
||
### Website toevoegen
|
||
|
||
1. Ga naar **Settings → Websites → Add website**
|
||
2. Vul in:
|
||
- **Name:** iso27diy.com
|
||
- **Domain:** iso27diy.com
|
||
3. Klik **Save**
|
||
4. Klik op het **tracking code** icoontje naast de website om je `data-website-id` te kopiëren
|
||
|
||
---
|
||
## Stap 8 — Tracking script toevoegen aan Netlify site
|
||
|
||
Voeg dit toe aan de `<head>` van je site. Hoe je dat doet hangt af van hoe je site gebouwd is, maar in de meeste gevallen is er een hoofd-HTML-template.
|
||
|
||
```html
|
||
<script
|
||
defer
|
||
src="https://analytics.iso27diy.com/script.js"
|
||
data-website-id="jouw-website-id-hier"
|
||
data-domains="iso27diy.com">
|
||
</script>
|
||
```
|
||
|
||
Het `data-domains` attribuut zorgt dat bezoeken vanaf andere domeinen (zoals localhost tijdens ontwikkeling) niet meegeteld worden.
|
||
|
||
Na een Netlify deploy: ga naar je site, wacht een paar seconden, en controleer of er een bezoek verschijnt in het Umami dashboard onder **Realtime**.
|
||
|
||
---
|
||
|
||
## Stap 9 — UTM-tracking testen
|
||
|
||
Maak een test-URL met UTM-parameters:
|
||
|
||
```
|
||
https://iso27diy.com/?utm_source=linkedin&utm_medium=post&utm_campaign=test&utm_content=cta-hero
|
||
```
|
||
|
||
Bezoek die URL in een browser. Ga dan in Umami naar:
|
||
|
||
**Reports → UTM** (of in het hoofddashboard onder **Sources**)
|
||
|
||
Je ziet daar de uitsplitsing per `source`, `medium`, `campaign` en `content`.
|
||
|
||
---
|
||
|
||
## Updates uitvoeren
|
||
|
||
Umami brengt regelmatig updates uit. Updaten gaat zo:
|
||
|
||
```bash
|
||
cd ~/umami
|
||
docker compose pull
|
||
docker compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## Database backup
|
||
|
||
Railway maakte geen automatische backups — op je eigen VPS ook niet, tenzij je dat instelt. Maak periodiek een handmatige backup:
|
||
|
||
```bash
|
||
docker compose exec db pg_dump -U umami umami > \
|
||
~/umami/backup-$(date +%Y%m%d).sql
|
||
```
|
||
|
||
Bewaar backups op een andere locatie (bijv. je lokale machine of een cloud opslag).
|
||
|
||
---
|
||
|
||
## Samenvatting gebruikte poorten en services
|
||
|
||
| Service | Poort | Bereikbaar vanaf |
|
||
| --------------- | ------- | -------------------- |
|
||
| Nginx | 80, 443 | Internet |
|
||
| Umami (Node.js) | 3000 | Alleen localhost |
|
||
| PostgreSQL | 5432 | Alleen Docker intern |
|