@@ -10,7 +10,7 @@
|
|||||||
storage.settings.storage.driver = "btrfs";
|
storage.settings.storage.driver = "btrfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
oci-containers.backend = "podman";
|
quadlet.autoEscape = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
settings.storage.storage.driver = "btrfs";
|
settings.storage.storage.driver = "btrfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtualisation.quadlet.autoEscape = true;
|
||||||
|
|
||||||
home = {
|
home = {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
podman-compose
|
podman-compose
|
||||||
|
@@ -32,10 +32,8 @@
|
|||||||
./users/nick
|
./users/nick
|
||||||
];
|
];
|
||||||
|
|
||||||
networking = {
|
# TODO: DNS for .local
|
||||||
hostName = "jupiter";
|
networking.hostName = "jupiter";
|
||||||
extraHosts = lib.strings.concatStringsSep "\n" [ "127.0.0.1 karaolidis.local" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/mnt/storage" = {
|
fileSystems."/mnt/storage" = {
|
||||||
label = "storage";
|
label = "storage";
|
||||||
|
@@ -8,7 +8,8 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
(import ./nginx { inherit user home; })
|
(import ./traefik { inherit user home; })
|
||||||
|
(import ./whoami { inherit user home; })
|
||||||
];
|
];
|
||||||
|
|
||||||
home-manager.users.${user} = {
|
home-manager.users.${user} = {
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ ! -d "/etc/letsencrypt/live/karaolidis.com" ]; then
|
|
||||||
certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d karaolidis.com -d '*.karaolidis.com' -d krlds.com -d '*.krlds.com' --non-interactive --agree-tos --email nick@karaolidis.com
|
|
||||||
else
|
|
||||||
certbot renew --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini
|
|
||||||
fi
|
|
@@ -1,93 +0,0 @@
|
|||||||
{
|
|
||||||
user ? throw "user argument is required",
|
|
||||||
home ? throw "home argument is required",
|
|
||||||
}:
|
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
hmConfig = config.home-manager.users.${user};
|
|
||||||
inherit (hmConfig.virtualisation.quadlet) networks volumes containers;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 0;
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
|
|
||||||
home-manager.users.${user} = {
|
|
||||||
sops = {
|
|
||||||
secrets."cloudflare/certbot".sopsFile = ../../../../../../../../secrets/personal/secrets.yaml;
|
|
||||||
templates."cloudflare.ini".content = ''
|
|
||||||
dns_cloudflare_api_token = ${hmConfig.sops.placeholder."cloudflare/certbot"}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.quadlet = {
|
|
||||||
networks.nginx.networkConfig = {
|
|
||||||
subnets = [ "10.89.0.0/16" ];
|
|
||||||
gateways = [ "10.89.0.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
volumes = {
|
|
||||||
nginx-log.volumeConfig = { };
|
|
||||||
nginx-cache.volumeConfig = { };
|
|
||||||
letsencrypt.volumeConfig = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
containers = {
|
|
||||||
certbot = {
|
|
||||||
containerConfig = {
|
|
||||||
autoUpdate = "registry";
|
|
||||||
image = "docker.io/certbot/dns-cloudflare";
|
|
||||||
volumes = [
|
|
||||||
"${volumes.letsencrypt.ref}:/etc/letsencrypt"
|
|
||||||
"${hmConfig.sops.templates."cloudflare.ini".path}:/etc/letsencrypt/cloudflare.ini:ro"
|
|
||||||
"${./certbot.sh}:/entrypoint.sh:ro"
|
|
||||||
];
|
|
||||||
entrypoint = "/entrypoint.sh";
|
|
||||||
};
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
Restart = "on-failure";
|
|
||||||
};
|
|
||||||
|
|
||||||
unitConfig = {
|
|
||||||
Wants = [ "network-online.target" ];
|
|
||||||
After = [
|
|
||||||
"network-online.target"
|
|
||||||
"sops-nix.service"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
nginx.containerConfig = {
|
|
||||||
autoUpdate = "registry";
|
|
||||||
image = "docker.io/library/nginx:latest";
|
|
||||||
networks = [ networks.nginx.ref ];
|
|
||||||
publishPorts = [
|
|
||||||
"80"
|
|
||||||
"443"
|
|
||||||
];
|
|
||||||
volumes = [
|
|
||||||
"${./nginx.conf}:/etc/nginx/nginx.conf:ro"
|
|
||||||
"${volumes.nginx-log.ref}:/var/log/nginx"
|
|
||||||
"${volumes.nginx-cache.ref}:/var/run/nginx/cache"
|
|
||||||
"${volumes.letsencrypt.ref}:/etc/letsencrypt:ro"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.user.timers.${containers.certbot._serviceName} = {
|
|
||||||
Timer = {
|
|
||||||
OnBootSec = "5min";
|
|
||||||
OnUnitActiveSec = "12h";
|
|
||||||
Persistent = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Install.WantedBy = [ "timers.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,73 +0,0 @@
|
|||||||
include /etc/nginx/modules/*.conf;
|
|
||||||
|
|
||||||
worker_processes auto;
|
|
||||||
pcre_jit on;
|
|
||||||
error_log stderr;
|
|
||||||
pid /run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
|
|
||||||
resolver 10.89.0.1 valid=30s;
|
|
||||||
server_tokens off;
|
|
||||||
|
|
||||||
map $http_upgrade $connection_upgrade {
|
|
||||||
default upgrade;
|
|
||||||
'' close;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_max_body_size 0;
|
|
||||||
client_body_buffer_size 128k;
|
|
||||||
large_client_header_buffers 4 16k;
|
|
||||||
sendfile on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
tcp_nopush on;
|
|
||||||
keepalive_timeout 30;
|
|
||||||
send_timeout 5m;
|
|
||||||
types_hash_max_size 2048;
|
|
||||||
variables_hash_max_size 2048;
|
|
||||||
|
|
||||||
gzip on;
|
|
||||||
gzip_disable "msie6";
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_buffers 16 8k;
|
|
||||||
gzip_http_version 1.1;
|
|
||||||
gzip_types
|
|
||||||
text/plain
|
|
||||||
text/css
|
|
||||||
text/javascript
|
|
||||||
text/xml
|
|
||||||
application/json
|
|
||||||
application/x-javascript
|
|
||||||
application/xml
|
|
||||||
application/xml+rss
|
|
||||||
font/eot
|
|
||||||
font/otf
|
|
||||||
font/ttf
|
|
||||||
image/svg+xml;
|
|
||||||
gzip_min_length 256;
|
|
||||||
|
|
||||||
proxy_cache_path /var/run/nginx/cache
|
|
||||||
levels=1:2
|
|
||||||
keys_zone=auth_cache:50m
|
|
||||||
keys_zone=default_cache:100m
|
|
||||||
max_size=10g
|
|
||||||
inactive=60m
|
|
||||||
use_temp_path=off;
|
|
||||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
|
||||||
proxy_cache_revalidate on;
|
|
||||||
proxy_cache_min_uses 1;
|
|
||||||
proxy_cache_background_update on;
|
|
||||||
proxy_cache_lock on;
|
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
}
|
|
@@ -0,0 +1,128 @@
|
|||||||
|
{
|
||||||
|
user ? throw "user argument is required",
|
||||||
|
home ? throw "home argument is required",
|
||||||
|
}:
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
hmConfig = config.home-manager.users.${user};
|
||||||
|
inherit (hmConfig.virtualisation.quadlet) networks volumes containers;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 0;
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
80
|
||||||
|
443
|
||||||
|
# TODO: Remove
|
||||||
|
8080
|
||||||
|
];
|
||||||
|
|
||||||
|
home-manager.users.${user} = {
|
||||||
|
sops = {
|
||||||
|
secrets."cloudflare/letsencrypt".sopsFile = ../../../../../../../../secrets/personal/secrets.yaml;
|
||||||
|
templates."traefik.env".content = ''
|
||||||
|
CF_DNS_API_TOKEN=${hmConfig.sops.placeholder."cloudflare/letsencrypt"}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.quadlet = {
|
||||||
|
networks.traefik.networkConfig = {
|
||||||
|
internal = true;
|
||||||
|
subnets = [ "10.89.0.0/16" ];
|
||||||
|
gateways = [ "10.89.0.1" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
volumes.letsencrypt.volumeConfig = { };
|
||||||
|
|
||||||
|
containers.traefik = {
|
||||||
|
containerConfig = {
|
||||||
|
autoUpdate = "registry";
|
||||||
|
image = "docker.io/library/traefik:latest";
|
||||||
|
exec = [
|
||||||
|
# TODO: Secure
|
||||||
|
"--api.insecure=true"
|
||||||
|
"--api.dashboard=true"
|
||||||
|
"--api.disabledashboardad=true"
|
||||||
|
|
||||||
|
"--providers.docker=true"
|
||||||
|
"--providers.docker.exposedbydefault=false"
|
||||||
|
|
||||||
|
"--entryPoints.web.address=:80"
|
||||||
|
"--entrypoints.web.http.redirections.entryPoint.to=websecure"
|
||||||
|
"--entrypoints.web.http.redirections.entryPoint.scheme=https"
|
||||||
|
"--entrypoints.web.forwardedHeaders.insecure=true"
|
||||||
|
|
||||||
|
"--entryPoints.websecure.address=:443"
|
||||||
|
"--entrypoints.websecure.http.tls=true"
|
||||||
|
"--entrypoints.websecure.http.tls.domains[0].main=karaolidis.com"
|
||||||
|
"--entrypoints.websecure.http.tls.domains[0].sans=*.karaolidis.com"
|
||||||
|
"--entrypoints.websecure.http.tls.domains[1].main=krlds.com"
|
||||||
|
"--entrypoints.websecure.http.tls.domains[1].sans=*.krlds.com"
|
||||||
|
"--entrypoints.websecure.forwardedHeaders.insecure=true"
|
||||||
|
|
||||||
|
"--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
|
||||||
|
"--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
|
||||||
|
"--certificatesresolvers.letsencrypt.acme.email=nick@karaolidis.com"
|
||||||
|
"--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||||
|
];
|
||||||
|
networks = [ networks.traefik.ref ];
|
||||||
|
# TODO: Remove
|
||||||
|
publishPorts = [
|
||||||
|
"0.0.0.0:8080:8080"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"/run/user/${
|
||||||
|
builtins.toString config.users.users.${user}.uid
|
||||||
|
}/podman/podman.sock:/var/run/docker.sock"
|
||||||
|
"${volumes.letsencrypt.ref}:/letsencrypt"
|
||||||
|
];
|
||||||
|
environmentFiles = [ hmConfig.sops.templates."traefik.env".path ];
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceConfig.Sockets = [
|
||||||
|
"traefik-http.socket"
|
||||||
|
"traefik-https.socket"
|
||||||
|
];
|
||||||
|
|
||||||
|
unitConfig = {
|
||||||
|
After = [
|
||||||
|
"traefik-http.socket"
|
||||||
|
"traefik-https.socket"
|
||||||
|
];
|
||||||
|
|
||||||
|
Requires = [
|
||||||
|
"traefik-http.socket"
|
||||||
|
"traefik-https.socket"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# https://github.com/eriksjolund/podman-traefik-socket-activation
|
||||||
|
systemd.user.sockets = {
|
||||||
|
"traefik-http" = {
|
||||||
|
Socket = {
|
||||||
|
ListenStream = "0.0.0.0:80";
|
||||||
|
FileDescriptorName = "web";
|
||||||
|
Service = "${containers.traefik._serviceName}.service";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "sockets.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"traefik-https" = {
|
||||||
|
Socket = {
|
||||||
|
ListenStream = "0.0.0.0:443";
|
||||||
|
FileDescriptorName = "websecure";
|
||||||
|
Service = "${containers.traefik._serviceName}.service";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "sockets.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
user ? throw "user argument is required",
|
||||||
|
home ? throw "home argument is required",
|
||||||
|
}:
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
hmConfig = config.home-manager.users.${user};
|
||||||
|
inherit (hmConfig.virtualisation.quadlet) networks;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home-manager.users.${user}.virtualisation.quadlet.containers.whoami.containerConfig = {
|
||||||
|
autoUpdate = "registry";
|
||||||
|
image = "docker.io/traefik/whoami:latest";
|
||||||
|
networks = [ networks.traefik.ref ];
|
||||||
|
labels = [
|
||||||
|
"traefik.enable=true"
|
||||||
|
|
||||||
|
"traefik.http.routers.whoami-public.rule=Host(`whoami.karaolidis.com`)"
|
||||||
|
"traefik.http.routers.whoami-public.entrypoints=websecure"
|
||||||
|
"traefik.http.routers.whoami-public.tls.certresolver=letsencrypt"
|
||||||
|
|
||||||
|
"traefik.http.routers.whoami-local.rule=Host(`whoami.karaolidis.local`)"
|
||||||
|
"traefik.http.routers.whoami-local.entrypoints=websecure"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user