Super useful NAS configuration of Pomerium
Pros / Cons
What’s great about doing things this way?
Most of all, this setup is convenient. I already had a NAS for backup purposes, being able to run very real software on the device is a nice plus. It’s a teeny-tiny little server that does almost everything I want in a self-hosted fashion. As much as I love all things Kubernetes, I wanted to keep the footprint small and single server and docker-compose is stupid simple to use, especially with Synology which natively supports intel based containers.
What are the drawbacks?
It’s not Kubernetes. I mean, I don’t need Kubernetes. But friends, who amongst us doesn’t love totally overbuilding their home labs? And, while this is all running on the same machine and the threat model isn’t really applicable to warrant it, I would love to be using something like Istio.
Services
- Grafana - Shows all the metrics about my little network. Though, these days I use Pomerium Enterprise for almost anything but app specific metrics.
- Prometheus - Prometheus collects and stores its metrics as time series data. I use it to pull metrics from Pomerium and my other cloud native tools and use Grafana to view that.
- Loki - Loki is a log aggregation system designed to store and query logs from all your applications and infrastructure. I use it for lightweight logging in grafana.
- Airdcpp - AirDC++ is a web client for Advanced Direct Connect and Direct Connect networks. Yes I am that old.
- Zipkin - Zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems. I mostly use it to trace and investigate long requests.
- archivebox - Archivebox lets me collect, save, and view sites offline. I like using it to read when I don’t have internet connections, or if I want to back up a copy of a site.
- code-server - I’ve used visual studio code as my daily driver for a while now. Code-server lets me hack from anywhere on Pomerium, behind Pomerium, in the browser. Doesn’t get cooler than that.
- Gitlab - Is the 900 pound gorilla (…and feels like it compared to the other containers) in the self-hosted source control management space. I mostly use it to backup my github repos, and work locally.
Tech Stack
- Docker
- Docker-compose
- Synology DSM
- DS918+ / INTEL Celeron J3455 / 8192 MB memory
Diagram
Soon ™️
Configs
docker-compose.yaml
:
version: "3"
services:
pomerium:
image: pomerium/pomerium:main
volumes:
- ./pomerium:/pomerium:ro
- ./pomerium:/data:rw
ports:
- "32443:443" # routers --> my nas
- "32080:80" # router --> my nas
expose:
- 5443
- 443
restart: always
verify:
image: pomerium/verify:latest
expose:
- 8000
restart: always
prometheus:
volumes:
- ./prometheus:/prometheus
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
image: prom/prometheus:latest
expose:
- 9090
restart: always
loki:
container_name: loki
image: grafana/loki:latest
expose:
- 3100
command: -config.file=/etc/loki/local-config.yaml
volumes:
- ./loki:/etc/loki
restart: always
grafana:
user: "104"
image: grafana/grafana
volumes:
- ./grafana:/var/lib/grafana
expose:
- 3000
restart: always
environment:
- "GF_AUTH_ANONYMOUS_ENABLED=true"
- "GF_AUTH_ANONYMOUS_ORG_ROLE=Admin"
- "GF_AUTH_DISABLE_LOGIN_FORM=true"
airdcpp:
image: gangefors/airdcpp-webclient:latest
volumes:
- /storage/tv:/tv:rw
- /storage/movies:/movies:rw
- ./.airdcpp:/.airdcpp:rw
user: root
expose:
- 5600
- 5601
ports:
- ${TCP_PORT:-21248}:${TCP_PORT:-21248}
- ${UDP_PORT:-21248}:${UDP_PORT:-21248}/udp
- ${TLS_PORT:-21249}:${TLS_PORT:-21249}
restart: always
codeserver:
image: codercom/code-server:latest
restart: always
expose:
- 8080
volumes:
- ".:/home/coder/project:rw"
- "$HOME/.config:/home/coder/.config"
command: --auth none --disable-telemetry
zipkin:
environment:
- STORAGE_TYPE=mem
- MYSQL_HOST=mysql
image: ghcr.io/openzipkin/zipkin-slim:${TAG:-latest}
expose:
- 9411
archivebox:
image: ${DOCKER_IMAGE:-archivebox/archivebox:master}
command: server --quick-init 0.0.0.0:8000
ports:
- 8000:8000
environment:
- ALLOWED_HOSTS=*
- MEDIA_MAX_SIZE=1g
volumes:
- /volume1/misc/archivebox:/data
gitlab:
container_name: gitlab
image: gitlab/gitlab-ee:latest
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.int.nas.redacted.io'
registry_external_url 'https://gitlab.int.nas.redacted.io'
letsencrypt['enable'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false
registry_nginx['listen_port'] = 80
registry_nginx['listen_https'] = false
pages_nginx['listen_port'] = 80
pages_nginx['listen_https'] = false
mattermost_nginx['listen_port'] = 80
mattermost_nginx['listen_https'] = false
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.sendgrid.net"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "apikey"
gitlab_rails['smtp_password'] = "REDACTED"
gitlab_rails['smtp_domain'] = "smtp.sendgrid.net"
gitlab_rails['smtp_authentication'] = "plain"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
gitlab_rails['gitlab_email_from'] = 'no-reply@redacted.io'
gitlab_rails['gitlab_email_reply_to'] = 'no-reply@redacted.io'
volumes:
- "./gitlab/config:/etc/gitlab"
- "./gitlab/logs:/var/log/gitlab"
- "./gitlab/data:/var/opt/gitlab"
expose:
- 80
- 443
- 22
restart: always
shm_size: "256m"
Pomerium
config.yaml
:
authenticate_service_url: https://authenticate.int.nas.redacted.io
signing_key: "REDACTED="
http_redirect_addr: ":80"
autocert: true
shared_secret: REDACTED=
cookie_secret: REDACTED=
idp_provider: google
idp_client_id: REDACTED.apps.googleusercontent.com
idp_client_secret: "REDACTED"
idp_service_account: REDACTED
# notice, I use the enterprise version of pomerium. Nearly all the route configurations are very standard with the exception of several (airdcpp, prometheus, grafana) require websockets.
policy:
- from: https://admin.int.nas.redacted.io
to: http://pomerium-enterprise:8701
pass_identity_headers: true
allowed_users:
- me
allowed_groups:
- my_family@redacted.io
- my_friends@redacted.io
Loki
config.yaml
:
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
ingester:
wal:
enabled: true
dir: /tmp/wal
lifecycler:
address: 127.0.0.1
ring:
kvstore:
store: inmemory
replication_factor: 1
final_sleep: 0s
chunk_idle_period: 1h # Any chunk not receiving new logs in this time will be flushed
max_chunk_age: 1h # All chunks will be flushed when they hit this age, default is 1h
chunk_target_size: 1048576 # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached first
chunk_retain_period: 30s # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m)
max_transfer_retries: 0 # Chunk transfers disabled
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /tmp/loki/boltdb-shipper-active
cache_location: /tmp/loki/boltdb-shipper-cache
cache_ttl: 24h # Can be increased for faster performance over longer query periods, uses more disk space
shared_store: filesystem
filesystem:
directory: /tmp/loki/chunks
compactor:
working_directory: /tmp/loki/boltdb-shipper-compactor
shared_store: filesystem
limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h
chunk_store_config:
max_look_back_period: 0s
table_manager:
retention_deletes_enabled: false
retention_period: 0s
ruler:
storage:
type: local
local:
directory: /tmp/loki/rules
rule_path: /tmp/loki/rules-temp
alertmanager_url: http://localhost:9093
ring:
kvstore:
store: inmemory
enable_api: true
Grafana
grafana.ini
:
[auth.jwt]
enabled = true
header_name = X-Pomerium-Jwt-Assertion
email_claim = email
jwk_set_url = https://authenticate.int.nas.redacted.io/.well-known/pomerium/jwks.json
cache_ttl = 60m
Screenshots
Pomerium and these apps are super lightweight. I have a few dozen more than covered here, but CPU / Memory is still very low.
Developing Pomerium in the browser, while behind Pomerium is about as inception-y as it gets.
Links and References
Many of these are – unsurprisingly – guides in our docs. Check them out.
- GitLab
- Grafana
- Synology
- JWT Verification (see how I set up Grafana!)
- code-server
Happy to answer any questions about my setup, or what trading files in the early 90s felt like.