More or less working

This commit is contained in:
Daniel Berteaud 2023-08-23 23:16:59 +02:00
parent 35e0c30287
commit 7a9ea28a2a
12 changed files with 409 additions and 109 deletions

View File

@ -0,0 +1,3 @@
Kind = "service-defaults"
Name = "unifi[[ .env.suffix ]]"
Protocol = "http"

View File

@ -0,0 +1,16 @@
Kind = "service-intentions"
Name = "unifi[[ .env.suffix ]]"
Sources = [
{
Name = "[[ .env.traefik ]]"
Permissions = [
{
Action = "allow"
HTTP {
PathPrefix = "/"
Methods = ["GET","HEAD","POST","PUT","DELETE"]
}
}
]
}
]

2
deps/common vendored

@ -1 +1 @@
Subproject commit 6c43f35bca0f6720c07c993a4b377047339cf591
Subproject commit f29c6673c2f476d58dd4dc36c4e758861f9c9104

View File

@ -1,7 +1,9 @@
FROM danielberteaud/alpine:latest AS builder
FROM alpine:latest AS builder
ARG UNIFI_VERSION=7.4.162
ENV JAVA_OPTS="-Djava.awt.headless=true"
RUN set -eu &&\
apk --no-cache add curl ca-certificates unzip &&\
cd /tmp &&\
@ -11,18 +13,22 @@ RUN set -eu &&\
FROM danielberteaud/java:11-alpine
MAINTAINER Daniel Berteaud <dbd@ehtrace.com>
COPY --from=build /tmp/UniFi /opt/unifi
COPY --from=builder /tmp/UniFi /opt/unifi
RUN set -eu &&\
apk --no-cache upgrade &&\
addgroup -g 8443 unifi &&\
adduser --system --ingroup unifi --disabled-password --uid 8443 --home /opt/unifi --shell /sbin/nologin unifi &&\
chown -R root:root /opt/unifi &&\
chown -R unifi:unifi /opt/unifi/dl &&\
chown -R :unifi /opt/unifi/conf &&\
chmod 750 /opt/unifi/conf
mkdir -p /data/unifi &&\
mkdir -p /data/logs &&\
chown unifi:unifi /data &&\
chmod 700 /data &&\
ln -s /data/unifi /opt/unifi/data &&\
ln -s /data/logs /opt/unifi/logs
EXPOSE 8443 8080 3778
USER unifi
VOLUME /data
CMD ["sh", "-c", "java ${JAVA_OPTS} -jar /opt/unifi/app/lib/ace.jar start"]
CMD ["sh", "-c", "java ${JAVA_OPTS} -jar /opt/unifi/lib/ace.jar start"]

View File

@ -0,0 +1,28 @@
#!/bin/sh
# vim: syntax=sh
set -euo pipefail
mkdir -p /data/unifi
mkdir -p /data/logs
if [ \! -f "/opt/unifi/data/system.properties" ]; then
echo "System initialization, copy the default system.properties"
cp /secrets/system.properties /opt/unifi/data/system.properties
else
for PROP in $(grep -vE '^(\s*$|#)' /secrets/system.properties); do
KEY=$(echo ${PROP} | cut -d= -f1)
VALUE=$(echo ${PROP} | cut -d= -f2)
if grep -q -E "^${KEY}=" /opt/unifi/data/system.properties; then
if grep -q -E "^${PROP}" /opt/unifi/data/system.properties; then
echo "${PROP} already set in system.properties"
else
echo "Updating ${PROP} in system.properties"
sed -i -E "s|^${KEY}=.*|${PROP}|" /opt/unifi/data/system.properties
fi
else
echo "Adding ${PROP} in system.properties"
echo ${PROP} >> /opt/unifi/data/system.properties
fi
done
fi

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight([%-5level]) %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@ -0,0 +1,10 @@
unifi.http.port=8080
unifi.https.port=8443
portal.http.port=8880
portal.https.port=8843
unifi.stun.port={{ env "NOMAD_PORT_stun" }}
unifi.db.nojournal=true
db.mongo.local=false
db.mongo.uri=mongodb://localhost:27017/unifi
statdb.mongo.uri=mongodb://localhost:27017/unifi_stats
unifi.db.name=unifi

View File

@ -0,0 +1,12 @@
net:
bindIp: 127.0.0.1
storage:
dbPath: /data/db
directoryPerDB: true
wiredTiger:
engineConfig:
directoryForIndexes: true
journalCompressor: snappy
collectionConfig:
blockCompressor: snappy

View File

@ -0,0 +1,65 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 127.0.0.1:8888;
server_name _;
server_tokens off;
root /usr/share/html;
[[- range $id, $header := slice "X-Forwarded-Client-Cert"
"X-Forwarded-Server"
"X-Envoy-Expected-Rq-Timeout-Ms"
"X-Envoy-Internal"
"Sec-Ch-Ua"
"Sec-Ch-Ua-Mobile"
"Sec-Ch-Ua-Platform"
"Sec-Fetch-Dest"
"Sec-Fetch-Mode"
"Sec-Fetch-Site"
"Sec-Fetch-User"
"Sec-Gpc"
"Upgrade-Insecure-Requests"
"Origin"
"Authorization" ]]
proxy_set_header [[ $header ]] "";
[[- end ]]
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_socket_keepalive on;
client_max_body_size 100m;
# Inform endpoint
location ~ ^/(inform|dl/firmware-cached).* {
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
proxy_set_header Host "[[ (urlParse .unifi.inform.public_url).Hostname ]]";
proxy_pass http://localhost:8080;
}
# Guest portal
location /guest/ {
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
proxy_set_header Host "[[ (urlParse .unifi.guest_portal.public_url).Hostname ]]";
proxy_pass http://ubnt.lapiole.org:8880;
}
# Main console
location / {
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$ ) {
return 405;
}
proxy_set_header Host "[[ (urlParse .unifi.controller.public_url).Hostname ]]";
proxy_pass https://localhost:8443;
}
}

View File

@ -1,42 +0,0 @@
## system.properties
#
# each unifi instance requires a set of ports:
#
## device inform
unifi.http.port={{ env "NOMAD_PORT_inform" }}
## controller UI / API
# unifi.https.port=8443
## portal redirect port for HTTP
portal.http.port=8880
## portal redirect port for HTTPs
# portal.https.port=8843
## local-bound port for DB server
# unifi.db.port=27117
## UDP port used for STUN
# unifi.stun.port=3478
#
## the IP devices should be talking to for inform
# system_ip=a.b.c.d
## disable mongodb journaling
# unifi.db.nojournal=false
## extra mongod args
# unifi.db.extraargs
#
## HTTPS options
# unifi.https.ciphers=TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA
# unifi.https.sslEnabledProtocols=TLSv1,SSLv2Hello
# unifi.https.hsts=false
# unifi.https.hsts.max_age=31536000
# unifi.https.hsts.preload=false
# unifi.https.hsts.subdomain=false
#
# Ports reserved for device redirector. There is no need to open
# firewall for these ports on controller, however do NOT set
# controller to use these ports.
#
# portal.redirector.port=8881
# portal.redirector.port.wired=8882
#
# Port used for throughput measurement.
# unifi.throughput.port=6789
#

View File

@ -1,6 +1,6 @@
job "unifi" {
datacenters = [[ .noamd.datacenters | toJSON ]]
datacenters = [[ .nomad.datacenters | toJSON ]]
group "controller" {
@ -9,11 +9,21 @@ job "unifi" {
port "stun" {}
}
service "unifi-inform" {
port = 8080
service {
name = "unifi[[ .env.suffix ]]"
port = 8888
connect {
sidecar_service {}
sidecar_service {
proxy {
[[- if has .proxy "service_name" ]]
upstreams {
destination_name = [[ .proxy.service_name | toJSON ]]
local_bind_port = 3128
}
[[- end ]]
}
}
sidecar_task {
[[ template "common/resources.tpl" .envoy ]]
}
@ -21,90 +31,203 @@ job "unifi" {
tags = [
"[[ .env.traefik ]].enable=true",
"[[ .env.traefik ]].http.routers.unifi-inform[[ .env.suffix ]].rule=Host(`[[ (urlParse .unifi.inform.public_url).Host ]]`) && (Path(`/inform`) || PathPrefix(`/dl/firmware-cached`))",
"[[ .env.traefik ]].http.routers.unifi-inform[[ .env.suffix ]].rule=Host(`
[[- (urlParse .unifi.inform.public_url).Hostname -]]
`) && (Path(`/inform`) || PathPrefix(`/dl/firmware-cached`))",
"[[ .env.traefik ]].http.routers.unifi-inform[[ .env.suffix ]].entrypoints=[[ join .unifi.inform.traefik.entrypoints "," ]]",
"[[ .env.traefik ]].http.routers.unifi-inform[[ .env.suffix ]].middlewares=[[ join .unifi.inform.traefik.middlewares "," ]]"
]
}
"[[ .env.traefik ]].http.routers.unifi-inform[[ .env.suffix ]].middlewares=[[ join .unifi.inform.traefik.middlewares "," ]]",
service "unifi-controller" {
port = 8443
connect {
sidecar_service {}
sidecar_task {
[[ template "common/resources.tpl" .envoy ]]
}
}
tags = [
"[[ .env.traefik ]].enable=true",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].rule=Host(`(urlParse .unifi.controller.public_url).Host`) && PathPrefix(`(urlParse .unifi.controller.public_url).Path`)",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].entrypoints=[[ join .unifi.controller.traefik.entrypoints ]]",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].rule=Host(`
[[- (urlParse .unifi.controller.public_url).Hostname -]]`)
[[- if ne "" (urlParse .unifi.controller.public_url).Path ]] && PathPrefix(`[[ (urlParse .unifi.controller.public_url).Path ]]`)[[ end ]]",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].entrypoints=[[ join .unifi.controller.traefik.entrypoints "," ]]",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].tls=true",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].scheme=https",
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].middlewares=[[ join .unifi.controller.traefik.middlewares "," ]]"
]
}
"[[ .env.traefik ]].http.routers.unifi-controller[[ .env.suffix ]].middlewares=[[ join .unifi.controller.traefik.middlewares "," ]]",
service "unifi-portal" {
port = 8880
connect {
sidecar_service {}
sidecar_task {
[[ template "common/resources.tpl" .envoy ]]
}
}
tags = [
"[[ .env.traefik ]].enable=true",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].rule=Host(`(urlParse .unifi.guest_portal.public_url).Host`) && PathPrefix(`/guest`)",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].entrypoints=[[ join .unifi.guest_portal.traefik.entrypoints ]]",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].rule=Host(`
[[- (urlParse .unifi.guest_portal.public_url).Hostname -]]
`) && PathPrefix(`/guest`)",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].entrypoints=[[ join .unifi.guest_portal.traefik.entrypoints "," ]]",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].tls=true",
"[[ .env.traefik ]].http.routers.unifi-portal[[ .env.suffix ]].middlewares=[[ join .unifi.guest_portal.traefik.middlewares "," ]]"
]
}
service "unifi-stun" {
service {
name = "unifi-stun[[ .env.suffix ]]"
port = "stun"
tags = [
"[[ .env.traefik ]].enable=true",
"[[ .env.traefik ]].udp.routers.unifi-stun[[ .env.suffix ]].entrypoints=[[ join .unifi.stun.traefik.middlewares "," ]]",
"[[ .env.traefik ]].udp.routers.unifi-stun[[ .env.suffix ]].entrypoints=[[ join .unifi.stun.traefik.entrypoints "," ]]",
"[[ .env.traefik ]].consulcatalog.connect=false"
]
}
}
[[ template "common/task.wait_for" dict
service {
name = "unifi-mongo[[ .env.suffix ]]"
port = 27017
connect {
sidecar_service {}
sidecar_task {
[[ template "common/resources.tpl" .envoy ]]
}
}
check {
type = "script"
command = "sh"
args = ["-c", "mongo --eval 'db.runCommand(\"ping\").ok'"]
interval = "30s"
timeout = "5s"
task = "mongo"
}
}
volume "unifi-data" {
type = [[ .unifi.controller.volume.type | toJSON ]]
source = [[ .unifi.controller.volume.source | toJSON ]]
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
volume "unifi-mongo" {
type = [[ .unifi.mongo.volume.type | toJSON ]]
source = [[ .unifi.mongo.volume.source | toJSON ]]
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
[[ template "common/task.wait_for.tpl" dict
"ctx" .
"SERVICE_1" "unifi-mongo" ]]
task "unifi" {
task "nginx" {
driver = [[ .unifi.nginx.driver | toJSON ]]
user = 8306
driver = [[ .unifi.controller.driver | toJSON ]]
lifecycle {
hook = "poststart"
sidecar = "true"
}
config {
image = [[ .unifi.controller.image | toJSON ]]
}
config {
image = [[ .unifi.nginx.image | toJSON ]]
volumes = ["local/nginx.conf:/etc/nginx/conf.d/default.conf"]
}
env {
[[ template "common/env.tpl" .unifi.controller.env ]]
}
template {
data =<<_EOF
[[ template "unifi/controller/system.properties" . ]]
template {
data =<<_EOF
[[ template "unifi/nginx/nginx.conf.tpl" . ]]
_EOF
destination = "secrets/system.properties"
destination = "local/nginx.conf"
}
[[ template "common/resources.tpl" .unifi.nginx.resources ]]
}
[[ template "common/resources.tpl" .unifi.controller.resources ]]
task "unifi" {
}
leader = true
driver = [[ .unifi.controller.driver | toJSON ]]
group "mongodb" {
config {
image = [[ .unifi.controller.image | toJSON ]]
volumes = [
"local/init-system.properties.sh:/entrypoint.d/10-init-system.properties.sh"
]
work_dir = "/local"
mount {
type = "tmpfs"
target = "/opt/unifi/run"
readonly = false
}
}
env {
JAVA_OPTS = "-Djava.awt.headless=true -Dlogback.configurationFile=/local/logback.xml
[[- if has .proxy "service_name" ]] -Dhttp.proxyHost=localhost -Dhttp.proxyPort=3128 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=3128 -Dhttp.nonProxyHosts=[[ join .proxy.no_proxy "|" ]][[ end ]]"
[[ template "common/env.tpl" .unifi.controller.env ]]
}
template {
data =<<_EOF
[[ template "unifi/controller/system.properties.tpl" . ]]
_EOF
destination = "secrets/system.properties"
}
template {
data =<<_EOF
[[ template "unifi/controller/logback.xml.tpl" ]]
_EOF
destination = "local/logback.xml"
}
template {
data =<<_EOF
[[ template "unifi/controller/init-system.properties.sh.tpl" . ]]
_EOF
destination = "local/init-system.properties.sh"
perms = "755"
}
volume_mount {
volume = "unifi-data"
destination = "/data"
}
[[ template "common/resources.tpl" .unifi.controller.resources ]]
}
task "mongo" {
driver = [[ .unifi.mongo.driver | toJSON ]]
lifecycle {
hook = "prestart"
sidecar = "true"
}
config {
image = [[ .unifi.mongo.image | toJSON ]]
args = [
"--config",
"/local/mongod.conf"
]
}
template {
data =<<_EOF
[[ template "unifi/mongo/mongod.conf.tpl" . ]]
_EOF
destination = "local/mongod.conf"
}
volume_mount {
volume = "unifi-mongo"
destination = "/data"
}
[[ template "common/resources.tpl" .unifi.mongo.resources ]]
}
task "whoami" {
driver = "docker"
config {
image = "traefik/whoami"
args = ["--port", "8787"]
}
resources {
cpu = 10
memory = 32
}
}
}
}

68
variables.yml Normal file
View File

@ -0,0 +1,68 @@
---
unifi:
controller:
driver: docker
image: danielberteaud/unifi:latest
resources:
cpu: 200
memory: 1024
env: {}
public_url: https://unifi.example.org
traefik:
entrypoints:
- https
middlewares:
- ip-trusted@file
volume:
type: csi
source: unifi-data
inform:
public_url: http://unifi-inform.example.org:8080/inform
traefik:
entrypoints:
- unifi-inform
middlewares:
- ip-trusted@file
guest_portal:
public_url: https://unifi-portal.example.org:8843/
traefik:
entrypoints:
- unifi-portal
middlewares:
- ip-guests@file
stun:
traefik:
entrypoints:
- unifi-stun
nginx:
image: nginxinc/nginx-unprivileged:alpine
driver: docker
resources:
cpu: 10
memory: 15
mongo:
image: mongo:3.6
driver: docker
resources:
cpu: 100
memory: 384
volume:
type: csi
source: unifi-mongo