Bekkalokk: Configure Gitea, clean web services

Update bekkalokk secrets format

Update gitea keys and firewall rules

Create gitea-user-import script

Fix SSH host key verification

Gitea-import-users bug squashification

Fix Gitea-import SSH problems
This commit is contained in:
2023-06-04 01:59:35 +02:00
committed by Felix Albrigtsen
parent db44bcf4bc
commit 8f55ef3193
9 changed files with 226 additions and 80 deletions

View File

@@ -9,10 +9,10 @@
#./services/keycloak.nix
# TODO: set up authentication for the following:
# ./services/website/website.nix
./services/website/nginx.nix
# ./services/website/gitea.nix
./services/website/mediawiki.nix
# ./services/website.nix
./services/nginx.nix
./services/gitea/default.nix
# ./services/mediawiki.nix
];
sops.defaultSopsFile = ../../secrets/bekkalokk/bekkalokk.yaml;

View File

@@ -0,0 +1,86 @@
{ config, values, pkgs, ... }:
let
cfg = config.services.gitea;
domain = "git2.pvv.ntnu.no";
sshPort = 2222;
in {
sops.secrets = {
"gitea/database" = {
owner = "gitea";
group = "gitea";
};
"gitea/passwd-ssh-key" = { };
"gitea/ssh-known-hosts" = { };
"gitea/import-user-env" = { };
};
services.gitea = {
enable = true;
stateDir = "/data/gitea";
appName = "PVV Git";
database = {
type = "postgres";
host = "postgres.pvv.ntnu.no";
port = config.services.postgresql.port;
passwordFile = config.sops.secrets."gitea/database".path;
createDatabase = false;
};
settings = {
server = {
DOMAIN = domain;
ROOT_URL = "https://${domain}/";
PROTOCOL = "http+unix";
SSH_PORT = sshPort;
};
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
database.LOG_SQL = false;
picture = {
DISABLE_GRAVATAR = true;
ENABLE_FEDERATED_AVATAR = false;
};
};
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://unix:${cfg.settings.server.HTTP_ADDR}";
recommendedProxySettings = true;
extraConfig = ''
client_max_body_size 512M;
'';
};
};
networking.firewall.allowedTCPPorts = [ sshPort ];
# Automatically import users
systemd.services.gitea-import-users = {
enable = true;
preStart=''${pkgs.rsync}/bin/rsync -e "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=$CREDENTIALS_DIRECTORY/ssh-known-hosts -i $CREDENTIALS_DIRECTORY/sshkey" -a pvv@smtp.pvv.ntnu.no:/etc/passwd /tmp/passwd-import'';
serviceConfig = {
ExecStart = pkgs.writers.writePython3 "gitea-import-users" { libraries = [ pkgs.python3Packages.requests ]; } (builtins.readFile ./gitea-import-users.py);
LoadCredential=[
"sshkey:${config.sops.secrets."gitea/passwd-ssh-key".path}"
"ssh-known-hosts:${config.sops.secrets."gitea/ssh-known-hosts".path}"
];
DynamicUser="yes";
EnvironmentFile=config.sops.secrets."gitea/import-user-env".path;
};
};
systemd.timers.gitea-import-users = {
enable = true;
requires = [ "gitea.service" ];
after = [ "gitea.service" ];
timerConfig = {
OnCalendar = "*-*-* 02:00:00";
Persistent = true;
Unit = "gitea-import-users.service";
};
};
}

View File

@@ -0,0 +1,82 @@
import requests
import secrets
import os
EMAIL_DOMAIN = os.getenv('EMAIL_DOMAIN')
if EMAIL_DOMAIN is None:
EMAIL_DOMAIN = 'pvv.ntnu.no'
API_TOKEN = os.getenv('API_TOKEN')
if API_TOKEN is None:
raise Exception('API_TOKEN not set')
GITEA_API_URL = os.getenv('GITEA_API_URL')
if GITEA_API_URL is None:
GITEA_API_URL = 'https://git2.pvv.ntnu.no/api/v1'
BANNED_SHELLS = [
"/usr/bin/nologin",
"/usr/sbin/nologin",
"/sbin/nologin",
"/bin/false",
"/bin/msgsh",
]
existing_users = []
def add_user(username, name):
if username in existing_users:
return
user = {
"email": username + '@' + EMAIL_DOMAIN,
"full_name": name,
"login_name": username,
"password": secrets.token_urlsafe(32),
"source_id": 1, # 1 = SMTP
"username": username,
"must_change_password": False,
"visibility": "private",
}
r = requests.post(GITEA_API_URL + '/admin/users', json=user,
headers={'Authorization': 'token ' + API_TOKEN})
if r.status_code != 201:
print('ERR: Failed to create user ' + username + ': ' + r.text)
return
print('Created user ' + username)
existing_users.append(username)
def main():
# Fetch existing users
r = requests.get(GITEA_API_URL + '/admin/users',
headers={'Authorization': 'token ' + API_TOKEN})
if r.status_code != 200:
raise Exception('Failed to get users: ' + r.text)
for user in r.json():
existing_users.append(user['login'])
# Read the file, add each user
with open("/tmp/passwd-import", 'r') as f:
for line in f.readlines():
uid = int(line.split(':')[2])
if uid < 1000:
continue
shell = line.split(':')[-1]
if shell in BANNED_SHELLS:
continue
username = line.split(':')[0]
name = line.split(':')[4]
add_user(username, name)
if __name__ == '__main__':
main()

View File

@@ -28,7 +28,7 @@ in {
database = {
type = "postgres";
host = values.hosts.postgres.ipv4;
host = "postgres.pvv.ntnu.no";
port = config.services.postgresql.port;
passwordFile = config.sops.secrets."keys/postgres/mediawiki".path;
createLocally = false;

View File

@@ -0,0 +1,44 @@
{ pkgs, config, ... }:
{
security.acme = {
acceptTerms = true;
defaults.email = "drift@pvv.ntnu.no";
};
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
#virtualHosts = {
# "bekkalokk.pvv.ntnu.no" = {
# forceSSL = true;
# enableACME = true;
# root = "${config.services.mediawiki.finalPackage}/share/mediawiki";
# locations = {
# "/" = {
# extraConfig = ''
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
# fastcgi_index index.php;
# fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
# include ${pkgs.nginx}/conf/fastcgi_params;
# include ${pkgs.nginx}/conf/fastcgi.conf;
# '';
# };
#
# "/images".root = config.services.mediawiki.uploadsDir;
#
# # "/git" = {
# # proxyPass = "http://unix:${config.services.gitea.settings.server.HTTP_ADDR}";
# # proxyWebsockets = true;
# # };
# };
# };
# };
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
}

View File

@@ -1,26 +0,0 @@
{ config, values, ... }:
{
sops.secrets."postgres/gitea/password" = { };
services.gitea = {
enable = true;
rootUrl = "https://git2.pvv.ntnu.no/";
stateDir = "/data/gitea";
appName = "PVV Git";
enableUnixSocket = true;
database = {
type = "postgres";
host = values.bicep.ipv4;
port = config.services.postgresql.port;
passwordFile = config.sops.secrets."postgres/gitea/password".path;
createDatabase = false;
};
settings = {
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
};
};
}

View File

@@ -1,42 +0,0 @@
{ pkgs, config, ... }:
{
security.acme = {
acceptTerms = true;
defaults.email = "drift@pvv.ntnu.no";
};
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts = {
"bekkalokk.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
root = "${config.services.mediawiki.finalPackage}/share/mediawiki";
locations = {
"/" = {
extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
};
"/images".root = config.services.mediawiki.uploadsDir;
# "/git" = {
# proxyPass = "http://unix:${config.services.gitea.settings.server.HTTP_ADDR}";
# proxyWebsockets = true;
# };
};
};
};
};
}