Migrated from multi repos to monorepo architecture.
This commit is contained in:
@@ -0,0 +1,384 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# Version tagging
|
||||
nextcloudVersion = "33.0.0";
|
||||
redisVersion = "8.6-alpine";
|
||||
databaseVersion = "11.8";
|
||||
onlyofficeVersion = "9.2";
|
||||
whiteboardVersion = "v1.5.6";
|
||||
# Helper
|
||||
helper = import ../service-helper.nix { inherit config pkgs lib; };
|
||||
cfg = config.numbus-server.services.nextcloud;
|
||||
# Container config
|
||||
name = "nextcloud";
|
||||
in
|
||||
|
||||
helper.mkPodmanService {
|
||||
inherit name;
|
||||
description = "Nextcloud, your own online office suite";
|
||||
defaultPort = "1100";
|
||||
middlewares = [
|
||||
"nextcloudSecureHeaders"
|
||||
];
|
||||
secrets = [
|
||||
"nextcloud/db_name"
|
||||
"nextcloud/db_username"
|
||||
"nextcloud/db_password"
|
||||
"nextcloud/redis_password"
|
||||
"nextcloud/onlyoffice_secret"
|
||||
"nextcloud/whiteboard_secret"
|
||||
];
|
||||
dirPermissions = [
|
||||
"100032:100 ${cfg.dataDir}"
|
||||
"100032:100 ${cfg.configDir}"
|
||||
"100032:100 ${cfg.configDir}/web"
|
||||
"100999:100 ${cfg.configDir}/redis"
|
||||
"100999:100 ${cfg.configDir}/database"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/log"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/cache"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/data"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/database"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
composeText = ''
|
||||
services:
|
||||
nextcloud-server:
|
||||
image: docker.io/library/nextcloud:${nextcloudVersion}
|
||||
container_name: nextcloud-server
|
||||
hostname: nextcloud-server
|
||||
networks:
|
||||
nextcloud:
|
||||
ipv4_address: 10.89.160.253
|
||||
ports:
|
||||
- "${cfg.port}:80/tcp"
|
||||
volumes:
|
||||
- ${cfg.configDir}/web:/var/www/html
|
||||
- ${cfg.dataDir}:/mnt/ncdata
|
||||
environment:
|
||||
MYSQL_HOST: nextcloud-database:3306
|
||||
MYSQL_DATABASE: ${config.sops.placeholder."nextcloud/db_name"}
|
||||
MYSQL_USER: ${config.sops.placeholder."nextcloud/db_username"}
|
||||
MYSQL_PASSWORD: ${config.sops.placeholder."nextcloud/db_password"}
|
||||
REDIS_HOST_PASSWORD: ${config.sops.placeholder."nextcloud/redis_password"}
|
||||
REDIS_HOST: nextcloud-redis
|
||||
NEXTCLOUD_TRUSTED_DOMAINS: ${cfg.subdomain}.${config.numbus-server.services.domain}
|
||||
NEXTCLOUD_DATA_DIR: /mnt/ncdata
|
||||
SMTP_SECURE: tls
|
||||
SMTP_HOST: ${config.numbus-server.mail.smtpServer}
|
||||
SMTP_PORT: ${toString config.numbus-server.mail.smtpPort}
|
||||
SMTP_NAME: ${config.numbus-server.mail.smtpUsername}
|
||||
SMTP_PASSWORD: ${config.sops.placeholder.smtpPassword}
|
||||
MAIL_FROM_ADDRESS: no-reply
|
||||
MAIL_DOMAIN: ${config.numbus-server.services.domain}
|
||||
APACHE_DISABLE_REWRITE_IP: 1
|
||||
OVERWRITEPROTOCOL: https
|
||||
TRUSTED_PROXIES: 10.89.160.1
|
||||
NC_default_phone_region: "${config.numbus-server.language}"
|
||||
NC_default_language: "${config.numbus-server.language}"
|
||||
NC_default_locale: "${config.numbus-server.locale}"
|
||||
NC_default_timezone: "${config.time.timeZone}"
|
||||
NC_maintenance_window_start: "1"
|
||||
depends_on:
|
||||
- nextcloud-database
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
restart: unless-stopped
|
||||
|
||||
nextcloud-redis:
|
||||
image: docker.io/library/redis:${redisVersion}
|
||||
container_name: nextcloud-redis
|
||||
hostname: nextcloud-redis
|
||||
user: '1000:1000'
|
||||
networks:
|
||||
nextcloud:
|
||||
ipv4_address: 10.89.160.252
|
||||
volumes:
|
||||
- ${cfg.configDir}/redis:/data
|
||||
command: redis-server --requirepass ${config.sops.placeholder."nextcloud/redis_password"} --save 60 1 --loglevel warning
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
restart: unless-stopped
|
||||
|
||||
nextcloud-database:
|
||||
image: docker.io/library/mariadb:${databaseVersion}
|
||||
container_name: nextcloud-database
|
||||
hostname: nextcloud-database
|
||||
user: '1000:1000'
|
||||
networks:
|
||||
nextcloud:
|
||||
ipv4_address: 10.89.160.251
|
||||
volumes:
|
||||
- ${cfg.configDir}/database:/var/lib/mysql
|
||||
environment:
|
||||
MARIADB_DATABASE: ${config.sops.placeholder."nextcloud/db_name"}
|
||||
MARIADB_USER: ${config.sops.placeholder."nextcloud/db_username"}
|
||||
MARIADB_PASSWORD: ${config.sops.placeholder."nextcloud/db_password"}
|
||||
MARIADB_RANDOM_ROOT_PASSWORD: true
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
command:
|
||||
- "--transaction-isolation=READ-COMMITTED"
|
||||
- "--binlog-format=ROW"
|
||||
restart: unless-stopped
|
||||
|
||||
nextcloud-onlyoffice:
|
||||
image: docker.io/onlyoffice/documentserver:${onlyofficeVersion}
|
||||
container_name: nextcloud-onlyoffice
|
||||
hostname: nextcloud-onlyoffice
|
||||
networks:
|
||||
nextcloud:
|
||||
ipv4_address: 10.89.160.250
|
||||
ports:
|
||||
- "9980:80/tcp"
|
||||
volumes:
|
||||
- ${cfg.configDir}/onlyoffice/log:/var/log/onlyoffice
|
||||
- ${cfg.configDir}/onlyoffice/cache:/var/lib/onlyoffice
|
||||
- ${cfg.configDir}/onlyoffice/data:/var/www/onlyoffice/Data
|
||||
- ${cfg.configDir}/onlyoffice/database:/var/lib/postgresql
|
||||
environment:
|
||||
- JWT_SECRET=${config.sops.placeholder."nextcloud/onlyoffice_secret"}
|
||||
- REDIS_SERVER_PASS=${config.sops.placeholder."nextcloud/redis_password"}
|
||||
- REDIS_SERVER_HOST=nextcloud-redis
|
||||
- REDIS_SERVER_PORT=6379
|
||||
- ADMINPANEL_ENABLED=false
|
||||
- EXAMPLE_ENABLED=false
|
||||
- METRICS_ENABLED=false
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
restart: unless-stopped
|
||||
|
||||
nextcloud-whiteboard:
|
||||
image: ghcr.io/nextcloud-releases/whiteboard:${whiteboardVersion}
|
||||
container_name: nextcloud-whiteboard
|
||||
hostname: nextcloud-whiteboard
|
||||
user: '1000:1000'
|
||||
ports:
|
||||
- "3002:3002/tcp"
|
||||
environment:
|
||||
NEXTCLOUD_URL: https://${cfg.subdomain}.${config.numbus-server.services.domain}
|
||||
JWT_SECRET_KEY: ${config.sops.placeholder."nextcloud/whiteboard_secret"}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
nextcloud:
|
||||
driver: bridge
|
||||
name: nextcloud
|
||||
ipam:
|
||||
config:
|
||||
- subnet: "10.89.160.0/24"
|
||||
gateway: "10.89.160.254"
|
||||
'';
|
||||
|
||||
extraOptions = {
|
||||
onlyoffice = {
|
||||
subdomain = mkOption {
|
||||
type = types.str;
|
||||
default = "onlyoffice";
|
||||
example = "onlyoffice";
|
||||
description = "The subdomain that onlyoffice for nextcloud will use";
|
||||
};
|
||||
};
|
||||
whiteboard = {
|
||||
subdomain = mkOption {
|
||||
type = types.str;
|
||||
default = "whiteboard";
|
||||
example = "whiteboard";
|
||||
description = "The subdomain that whiteboard for nextcloud will use";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = {
|
||||
sops.templates."traefik/rules/nextcloud-onlyoffice" = {
|
||||
gid = "100";
|
||||
uid = "100999";
|
||||
mode = "0400";
|
||||
content = ''
|
||||
http:
|
||||
routers:
|
||||
nextcloud-onlyoffice:
|
||||
rule: "Host(`${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain}`)"
|
||||
entrypoints:
|
||||
- "websecure"
|
||||
service: nextcloud-onlyoffice
|
||||
tls:
|
||||
certresolver: "cloudflare"
|
||||
options: "secureTLS"
|
||||
services:
|
||||
nextcloud-onlyoffice:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://host.containers.internal:9980"
|
||||
'';
|
||||
path = "/etc/traefik/rules/nextcloud-onlyoffice.yaml";
|
||||
};
|
||||
|
||||
sops.templates."traefik/rules/nextcloud-whiteboard" = {
|
||||
gid = "100";
|
||||
uid = "100999";
|
||||
mode = "0400";
|
||||
content = ''
|
||||
http:
|
||||
routers:
|
||||
nextcloud-whiteboard:
|
||||
rule: "Host(`${cfg.whiteboard.subdomain}.${config.numbus-server.services.domain}`)"
|
||||
entrypoints:
|
||||
- "websecure"
|
||||
service: nextcloud-whiteboard
|
||||
middlewares:
|
||||
- "secureHeaders"
|
||||
tls:
|
||||
certresolver: "cloudflare"
|
||||
options: "secureTLS"
|
||||
services:
|
||||
nextcloud-whiteboard:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://host.containers.internal:3002"
|
||||
'';
|
||||
path = "/etc/traefik/rules/nextcloud-whiteboard.yaml";
|
||||
};
|
||||
|
||||
sops.templates."traefik/rules/nextcloud-secureHeaders" = {
|
||||
gid = "100";
|
||||
uid = "100999";
|
||||
mode = "0400";
|
||||
content = ''
|
||||
http:
|
||||
middlewares:
|
||||
nextcloudSecureHeaders:
|
||||
headers:
|
||||
FrameDeny: false
|
||||
CustomFrameOptionsValue: "SAMEORIGIN"
|
||||
AddVaryHeader: true
|
||||
BrowserXssFilter: true
|
||||
ContentTypeNosniff: true
|
||||
ForceSTSHeader: true
|
||||
STSSeconds: 315360000
|
||||
STSIncludeSubdomains: true
|
||||
STSPreload: true
|
||||
AccessControlAllowMethods: "GET,OPTIONS,PUT"
|
||||
AccessControlAllowOriginList:
|
||||
- origin-list-or-null
|
||||
AccessControlMaxAge: 100
|
||||
ReferrerPolicy: same-origin
|
||||
PermissionsPolicy: "vibrate=()"
|
||||
ContentSecurityPolicy: >-
|
||||
default-src https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain} 'self';
|
||||
script-src https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain} 'self' 'unsafe-inline';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
connect-src 'self';
|
||||
img-src 'self' data:;
|
||||
font-src 'self' data:;
|
||||
frame-src https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain} 'self';
|
||||
frame-ancestors https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain} 'self';
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
'';
|
||||
path = "/etc/traefik/rules/nextcloud-secureHeaders";
|
||||
};
|
||||
|
||||
systemd.services."${name}-quirk" = {
|
||||
description = "Podman container quirk : ${name}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "${name}.service" "${name}-secrets.service" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
startLimitBurst = 5;
|
||||
startLimitIntervalSec = 600;
|
||||
path = [ pkgs.coreutils pkgs.sudo pkgs.podman pkgs.systemd pkgs.gnugrep ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
OCC="sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ"
|
||||
|
||||
[[ ! -e /var/lib/numbus-server/${name}/.env ]] && systemctl start ${name}-secrets.service
|
||||
until [[ -e /var/lib/numbus-server/${name}/.env ]]; do
|
||||
echo "Waiting for secrets generation..."
|
||||
sleep 5
|
||||
done
|
||||
source /var/lib/numbus-server/${name}/.env
|
||||
|
||||
until $OCC status | grep -iq "installed: true" >/dev/null 2>&1; do
|
||||
echo "Waiting for Nextcloud to be up and running..."
|
||||
sleep 60
|
||||
done
|
||||
|
||||
$OCC db:add-missing-indices
|
||||
$OCC maintenance:repair --include-expensive
|
||||
|
||||
INSTALL_APPS_LIST=( "calendar" "contacts" "mail" "notes" "onlyoffice" "cookbook" "whiteboard" )
|
||||
DISABLE_APPS_LIST=( "activity" "federation" "webhook_listeners" "photos" "recommendations" "sharebymail" "teams" "support" "richdocumentscode" )
|
||||
|
||||
for app in ''${INSTALL_APPS_LIST[@]}; do
|
||||
if ! $OCC --no-warnings app:list | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:install "$app"
|
||||
fi
|
||||
if $OCC --no-warnings app:list --disabled | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:enable "$app"
|
||||
fi
|
||||
done
|
||||
for app in ''${DISABLE_APPS_LIST[@]}; do
|
||||
if $OCC --no-warnings app:list --enabled | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:disable "$app"
|
||||
fi
|
||||
done
|
||||
$OCC --no-warnings config:system:set onlyoffice DocumentServerInternalUrl --value="https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain}/"
|
||||
$OCC --no-warnings config:system:set onlyoffice DocumentServerUrl --value="https://${cfg.onlyoffice.subdomain}.${config.numbus-server.services.domain}/"
|
||||
$OCC --no-warnings config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_PASSWORD"
|
||||
$OCC --no-warnings config:app:set whiteboard collabBackendUrl --value="https://${cfg.whiteboard.subdomain}.${config.numbus-server.services.domain}"
|
||||
$OCC --no-warnings config:app:set whiteboard jwt_secret_key --value="$WHITEBOARD_PASSWORD"
|
||||
|
||||
if [[ ! -f /var/lib/numbus-server/${name}/croned.true ]]; then
|
||||
$OCC background:cron
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php
|
||||
touch /var/lib/numbus-server/${name}/croned.true
|
||||
fi
|
||||
|
||||
if [[ ! -f /var/lib/numbus-server/${name}/scanned.true ]]; then
|
||||
$OCC files:scan --all
|
||||
$OCC files:repair-tree
|
||||
touch /var/lib/numbus-server/${name}/scanned.true
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services."${name}-cron" = {
|
||||
description = "Podman container crontab : ${name}";
|
||||
after = [ "${name}.service" "${name}-quirk.service" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
path = [ pkgs.sudo pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecCondition = ''${pkgs.sudo}/bin/sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ status'';
|
||||
ExecStart = "${pkgs.sudo}/bin/sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers."${name}-cron" = {
|
||||
description = "Timer for Nextcloud cron";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = "5m";
|
||||
OnUnitActiveSec = "5m";
|
||||
Unit = "${name}-cron.service";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user