init commit

This commit is contained in:
rskntroot
2025-03-11 06:03:13 +00:00
commit 12941cd2c5
12 changed files with 319 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
mkdocs/site
traefik/log/*.log
traefik/log/*.gz
traefik/tls/*.json
.local

63
README.md Normal file
View File

@@ -0,0 +1,63 @@
# Headquarters
Services
- traefik as front end proxy, tls, and http3
- traefik dashboard behind mtls
- squidfunk/mkdocs-material to build static html
- nginx to host static html
- jellyfin for streaming service
## Setup
``` bash
docker compose up -d
```
## Requirements
### Traefik Logging
expects `/var/log/traefik` to exist
``` bash
sudo mkdir -p /var/log/traefik
```
### Rskio Website
expects `../rskio/mkdocs` to exist
``` bash
git clone https://github.com/rskntroot/rskio.git
```
### Jellyfin
expects `/mnt/jellyfin` and `/mnt/media` to exist
#### setup creds
``` bash
sudo mkdir -p /etc/smb/creds
sudo vi /etc/smb/creds/share
sudo chmod 600 /etc/smb/creds/share
```
create creds files in the format
```
username=<user>
password=<pass>
```
#### edit fstab
``` zsh
vi /etc/fstab
```
``` fstab
//192.168.1.179/Media /mnt/media cifs credentials=/etc/smb/creds/media,iocharset=utf8,vers=3.0,uid=1000,gid=1000,file_mode=0660,dir_mode=0770 0 0
//192.168.1.179/Jellyfin /mnt/jellyfin cifs credentials=/etc/smb/creds/jellyfin,iocharset=utf8,vers=3.0,uid=1000,gid=1000,file_mode=0660,dir_mode=0770 0 0
```

65
compose.yml Normal file
View File

@@ -0,0 +1,65 @@
services:
mkdocs:
image: squidfunk/mkdocs-material
command:
- build
volumes:
- ./mkdocs:/docs
traefik:
image: traefik:latest
command:
- --configFile=/etc/traefik/traefik.yml
ports:
- 80:80/tcp
- 443:443/tcp
- 443:443/udp
- 8080:8080/tcp
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/log/traefik:/var/log/traefik
- ./traefik/etc:/etc/traefik:ro
- ./traefik/tls:/letsencrypt
nginx:
image: nginx:latest
restart: unless-stopped
labels:
- traefik.enable=true
- traefik.http.routers.rskio.entrypoints=websecure
- traefik.http.routers.rskio.rule=Host(`docs.rskio.com`)
- traefik.http.routers.rskio.tls=true
- traefik.http.routers.rskio.tls.options=docs@file
- traefik.http.routers.rskio.tls.certresolver=rskio_certresolver
- traefik.http.routers.rskio.service=rskio@docker
- traefik.http.services.rskio.loadbalancer.server.port=80
- traefik.http.routers.rskio.middlewares=secureHeaders@file
volumes:
- ./mkdocs/site:/opt/share/mkdocs/html:ro
- ./nginx/etc/conf.d:/etc/nginx/conf.d:ro
depends_on:
mkdocs:
condition: service_completed_successfully
stream:
image: jellyfin/jellyfin
labels:
- traefik.enable=true
- traefik.http.routers.stream.entrypoints=websecure
- traefik.http.routers.stream.rule=Host(`stream.rskio.com`)
- traefik.http.routers.stream.tls=true
- traefik.http.routers.stream.tls.certresolver=rskio_certresolver
- traefik.http.routers.stream.service=stream@docker
- traefik.http.services.stream.loadbalancer.server.port=8096
tty: true
restart: unless-stopped
devices:
- /dev/dri:/dev/dri
volumes:
- ./jellyfin/config:/config
- ./jellyfin/cache:/cache
- /mnt/media:/data
ports:
- 8096:8096
environment:
- TZ=US/Mountain

1
jellyfin Symbolic link
View File

@@ -0,0 +1 @@
/mnt/jellyfin

1
mkdocs Symbolic link
View File

@@ -0,0 +1 @@
../rskio/mkdocs

View File

@@ -0,0 +1,31 @@
server {
listen 80;
listen [::]:80;
server_name rskio.com;
server_tokens off;
add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header X-XSS-Protection "1; mode=block";
# rskio logging is handled via traefik
#access_log /var/log/nginx/host.access.log main;
location / {
root /opt/share/mkdocs/html;
index index.html index.htm;
limit_except GET HEAD POST { deny all; }
}
# rskio auth is handled via traefik
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
limit_except GET HEAD POST { deny all; }
}
}

14
rskio.service Normal file
View File

@@ -0,0 +1,14 @@
[Unit]
Description=Rskio Website
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/docker/rskio
ExecStart=/bin/bash -c "docker compose -f ./compose.yml up -d"
ExecStop=/bin/bash -c "docker compose -f ./compose.yml down"
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIF/zCCA+egAwIBAgIUUiRAdfNY8+cPZkIoKgYmCaHwb6wwDQYJKoZIhvcNAQEL
BQAwgY0xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwG
RGVudmVyMRIwEAYDVQQKDAlSc2tpbyBMdGQxFDASBgNVBAsMC0RldmVsb3BtZW50
MREwDwYDVQQDDAhyc2tpby1jYTEdMBsGCSqGSIb3DQEJARYObG9zdEByc2tpby5j
b20wIBcNMjUwMzA0MDc0NDQwWhgPMjA1MjA3MjAwNzQ0NDBaMIGNMQswCQYDVQQG
EwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjESMBAGA1UE
CgwJUnNraW8gTHRkMRQwEgYDVQQLDAtEZXZlbG9wbWVudDERMA8GA1UEAwwIcnNr
aW8tY2ExHTAbBgkqhkiG9w0BCQEWDmxvc3RAcnNraW8uY29tMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEArCrI30KsrX1fywvJt3klEZXmOZaFFIl+p86c
DC80HpBQ4YRlkWrXYor5jVPNNZMSAx9Vcu8DVqRjysHtRpajgQtNdWrpmbqH/F1r
gcdHciedTJqxnE3JAA95hVJYewWsvInUzcgmsvYehEUGnYvFeN+rxfDBMiUDFcav
r+FyNk51PTUb+zRdGwwrLvBN86Kc8oyjK7T8q8c10BHD0ESDOY4SeRU0ap0VpsVN
EaGfuO5+eHqUMXj5OvoI8mzjPVZ/ELLDlFRxQVZAzcLRAXIHzIXlt2ROl5dypXyE
l++0kVZBBk0qVLk95r8w+sYzaMH5zPUp4UFQjLFSSgyCpWpzwWrbyOdvDzcVJ3As
8A/8lqSThbCIbHLXllqQO0Oi3oSZQm/Crn3aQw5kOUwYEyJvnlSXXMcvkHVQgLv/
Uhl0OlQfSjwIEzL0Ezti/9kmAVHUvxBbEWu2zq5g8/3zzaVU6FX9EdPNsVTTk9Qw
RxslLWWtUtlkhtOjD6EoruboFDxlTC7sfTrWsUF9+5O11xbowmvHPycs2QE8fn13
paYmMLMq4XNtjErKKlYUh12/Ysca91FwUX6+JQtygzrwf0kX1ZY5oW+QpjnRAL+q
+7JD+uP14VrsJTN781e615icI0RcMvpyfnf2za6TZR8U0bov224M+kdgaAKae2jb
h/cjLVsCAwEAAaNTMFEwHQYDVR0OBBYEFL5x8cKfmeYPZ/bcm4p6xfCWwwVHMB8G
A1UdIwQYMBaAFL5x8cKfmeYPZ/bcm4p6xfCWwwVHMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggIBAATyoT95B5MiXmbt6PW00Gkn16RBLORTFJ6CrRB8
J03bSYUk8H4xyT9C4jvi+HDQD66zPaMmMwoy5sSx0XUdNa+wZNTztUaKiDa9XPyU
osztloZgH6heheyls4TCexHDmVjwPndYXLDg9X8gUIdw2hFYcjrtyRFeUuDIvQ8b
XVrTAZ3iaPWsPYEV+PvY3EaSbTLJWmTEIbYEbx3XGIkSSsYTEqJqWaMkxlHxTJK+
mruk7mqGeCNgyrbX7jvyxqF+U0lWG2dgw+2z70+c4uOfA3hVAcZDQAXHT1DOdDde
WnZ1g0WH/VktF61ldd7F34ljBfVsGTvfem/gwHdjplf8eavw6L8f4bV1UbM3j7TM
rtaNN4+Gb+1gmBMzkHpQFMF1jQifrDEhytnpRd6CP0rtzYjg6IwcRdeTTQtsI1y9
hiEP+FRsZbj2QV7wNMfmCQG8/QAsrAVaAho6MmTlPoZaIXdiVBJPALBkfJUIUII4
OqgAWF4uAqxQx1iUOkeq/+RQtUCMQol0k20UBA4rGQbw7WjCYhJq1DdCsYsCka6N
rUfTI5tZSM9bUNbCabsn56OWERx0KRjY4hTZqrlbjOpnAuOF0qqUcxLhgwgtLbWz
5eJz/ulkMtv/1woK0EqPHiDl4DqX1PIGNQFxTFJqvOC7a4Emokij6VOiz96H7mqK
Oxh9
-----END CERTIFICATE-----

56
traefik/etc/dynamic.yml Normal file
View File

@@ -0,0 +1,56 @@
tls:
options:
docs:
minVersion: VersionTLS13
cipherSuites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_FALLBACK_SCSV
dashboard:
minVersion: VersionTLS13
cipherSuites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_FALLBACK_SCSV
clientAuth:
caFiles:
- /etc/traefik/com.rskio.ca.crt
clientAuthType: RequireAndVerifyClientCert
http:
routers:
traefik-dashboard:
rule: "Host(`oxy.rskio.com`)"
service: "api@internal"
entryPoints:
- "websecure"
middlewares:
- "redirect-dashboard"
tls:
options: dashboard@file
certResolver: rskio_certresolver
middlewares:
redirect-dashboard:
redirectRegex:
regex: "^https?://([^/]+)/?$"
replacement: "https://${1}/dashboard/"
permanent: true
secureHeaders:
headers:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: true
referrerPolicy: "same-origin"
sslRedirect: true
stsSeconds: 31536000

44
traefik/etc/traefik.yml Normal file
View File

@@ -0,0 +1,44 @@
global:
checkNewVersion: false
sendAnonymousUsage: false
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
priority: 10
websecure:
address: :443
http3:
advertisedPort: 443
certificatesResolvers:
rskio_certresolver:
acme:
tlsChallenge: {}
email: rskntroot@gmail.com
storage: /letsencrypt/acme.json
log:
level: INFO
format: json
filePath: /var/log/traefik/traefik.log
accessLog:
format: json
filePath: /var/log/traefik/access.log
api:
dashboard: true
providers:
docker:
endpoint: unix:///var/run/docker.sock
network: hq_default
exposedByDefault: false
file:
filename: /etc/traefik/dynamic.yml
watch: true

1
traefik/log Symbolic link
View File

@@ -0,0 +1 @@
/var/log/traefik/

3
traefik/tls/.required.md Normal file
View File

@@ -0,0 +1,3 @@
# Required
this dir is required to enable traefik letsencrypt