mirror of
https://git.sr.ht/~magic_rb/cluster
synced 2024-11-25 09:36:14 +01:00
parent
0d81433c2d
commit
594065f99b
|
@ -1,6 +1,5 @@
|
|||
{ pkgs, nixpkgs, ... }@inputs:
|
||||
let
|
||||
ldflags = "-s -w -extldflags '-static'";
|
||||
csi-driver-nfs = pkgs.buildGoModule {
|
||||
name = "csi-driver-nfs";
|
||||
version = "2.0";
|
||||
|
@ -11,8 +10,10 @@ let
|
|||
|
||||
src = inputs.csi-driver-nfs;
|
||||
};
|
||||
init = pkgs.writeShellScriptBin "init" ''
|
||||
${csi-driver-nfs}/bin/nfsplugin $@
|
||||
init = with pkgs; pkgs.writeShellScriptBin "init" ''
|
||||
export "PATH=${busybox}/bin:$PATH"
|
||||
echo $PATH
|
||||
exec ${csi-driver-nfs}/bin/nfsplugin $@
|
||||
'';
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
{
|
||||
security.oauth2JwtSecret = "STUFF";
|
||||
security.internalToken = "STUFF";
|
||||
security.secretKey = "STUFF";
|
||||
lfs.lfsJwtSecret = "STUFF";
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
gid = 5000
|
||||
uid = 5000
|
||||
app_ini = "/app.ini"
|
||||
app_ini_overwrite = true
|
|
@ -1,18 +1,8 @@
|
|||
{ pkgs, system, nixpkgs, ... }:
|
||||
let
|
||||
# pkgs = (import nixpkgs { inherit system; }).pkgsMusl;
|
||||
contents = let
|
||||
defaults = {
|
||||
userUid = builtins.toString 5001;
|
||||
userGid = builtins.toString 5001;
|
||||
user = "gitea";
|
||||
data = "/data/gitea";
|
||||
};
|
||||
custom = rec {
|
||||
gitea = pkgs.gitea.override {
|
||||
inherit openssh git;
|
||||
pamSupport = false;
|
||||
};
|
||||
gitea =
|
||||
let
|
||||
openssh = pkgs.openssh.override {
|
||||
withKerberos = false; withFIDO = false;
|
||||
};
|
||||
|
@ -26,19 +16,29 @@ let
|
|||
withpcre2 = false;
|
||||
sendEmailSupport = false;
|
||||
};
|
||||
};
|
||||
bashLib = ../bash-lib;
|
||||
in
|
||||
pkgs.symlinkJoin { name = "contents"; paths = [ custom.gitea ]; };
|
||||
init = "${pkgs.rust-runner}/bin/gitea";
|
||||
in
|
||||
pkgs.gitea.override {
|
||||
inherit openssh git;
|
||||
pamSupport = false;
|
||||
};
|
||||
bashLib = ../bash-lib;
|
||||
init = pkgs.writeShellScriptBin "init" (builtins.readFile ./init);
|
||||
conf = pkgs.writeText "conf" ''
|
||||
_prog_busybox="${pkgs.busybox}"
|
||||
_prog_bashlib="${bashLib}"
|
||||
_prog_bash="${pkgs.bash}"
|
||||
_prog_gitea="${pkgs.gitea}"
|
||||
|
||||
_conf_user_uid="5000"
|
||||
_conf_user_gid="5000"
|
||||
_conf_data="/data/gitea"
|
||||
'';
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
name = "gitea";
|
||||
tag = "latest";
|
||||
|
||||
inherit contents;
|
||||
|
||||
config = {
|
||||
Entrypoint = [ "${init}" ];
|
||||
Entrypoint = [ "${init}/bin/init" "${conf}" ];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,8 +6,5 @@ services:
|
|||
- "3000:3000"
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./config.toml
|
||||
target: /config.toml
|
||||
- type: bind
|
||||
source: ./config.toml
|
||||
source: $PWD/app.ini
|
||||
target: /app.ini
|
||||
|
|
71
docker/gitea/init
Normal file
71
docker/gitea/init
Normal file
|
@ -0,0 +1,71 @@
|
|||
# -*- mode: shell-script; -*-
|
||||
|
||||
if [[ ! -f /env ]]
|
||||
then
|
||||
conf=$1 ; shift 1
|
||||
source $conf
|
||||
else
|
||||
source /env || \
|
||||
echo_exit "Failed to source env!"
|
||||
source $conf
|
||||
fi
|
||||
|
||||
source $_prog_bashlib/main.bash
|
||||
|
||||
if [[ $($_prog_busybox/bin/id -u) = 0 ]] ; then
|
||||
$_prog_busybox/bin/cat << EOF
|
||||
### Gitea Nix Image Manual
|
||||
##
|
||||
## USER_UID ? $_conf_user_uid - default user id
|
||||
## USER_GID ? $_conf_user_gid - default group id
|
||||
|
||||
### You must place a \`app.ini\` at \`/app.ini\`
|
||||
|
||||
### Volume Mounts
|
||||
##
|
||||
## - $_conf_data - Gitea base data folder
|
||||
|
||||
EOF
|
||||
|
||||
default_opt USER_UID "$_conf_user_uid"
|
||||
default_opt USER_GID "$_conf_user_gid"
|
||||
|
||||
$_prog_busybox/bin/cat << EOF
|
||||
### Starting with options:
|
||||
## USER_UID = "$_user_uid"
|
||||
## USER_GID = "$_user_gid"
|
||||
EOF
|
||||
|
||||
(
|
||||
set -e
|
||||
echo "gitea:x:$_user_uid:$_user_gid:Gitea:$_conf_data:$_prog_bash/bin/bash" > /etc/passwd
|
||||
echo "gitea:x:$_user_gid:" > /etc/group
|
||||
) || echo_exit "Failed to create user and group!"
|
||||
|
||||
[[ ! -d $_conf_data ]] && mkdir_chown $_conf_data "$_user_uid" "$_user_gid"
|
||||
mkdir_chown /tmp "$_user_uid" "$_user_gid"
|
||||
|
||||
$_prog_busybox/bin/mkdir -p /usr/bin
|
||||
$_prog_busybox/bin/ln -s $_prog_busybox/bin/env /usr/bin/env
|
||||
|
||||
check_owner "$_conf_data" "$_user_uid" "$_user_gid"
|
||||
|
||||
save_env "_user_uid \
|
||||
_user_gid \
|
||||
conf
|
||||
" > /env # TODO: exited even though it must have succeded || \
|
||||
# echo_exit "Failed to save environment!"
|
||||
|
||||
check_root "$_user_uid"
|
||||
exec $_prog_busybox/bin/su gitea -c "$0 $@" || \
|
||||
echo_exit "Failed to switch user!"
|
||||
else
|
||||
source /env || \
|
||||
echo_exit "Failed to source env!"
|
||||
|
||||
export GITEA_WORK_DIR=$_conf_data
|
||||
|
||||
echo
|
||||
echo "Starting Gitea!"
|
||||
$_prog_gitea/bin/gitea -c /app.ini $@
|
||||
fi
|
|
@ -1,337 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config;
|
||||
|
||||
useMysql = cfg.database.type == "mysql";
|
||||
usePostgresql = cfg.database.type == "postgres";
|
||||
useSqlite = cfg.database.type == "sqlite3";
|
||||
|
||||
format = pkgs.formats.ini { mkKeyValue = generators.mkKeyValueDefault {} "="; };
|
||||
in
|
||||
|
||||
|
||||
{
|
||||
options = {
|
||||
run = mkOption {
|
||||
type = types.package;
|
||||
description = "Run gitea derivation.";
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
default = "/gitea";
|
||||
type = types.str;
|
||||
description = "gitea data directory.";
|
||||
};
|
||||
|
||||
uid = mkOption {
|
||||
default = 5000;
|
||||
type = types.int;
|
||||
description = "gitea user id.";
|
||||
};
|
||||
|
||||
gid = mkOption {
|
||||
default = 5000;
|
||||
type = types.int;
|
||||
description = "gitea group id.";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
default = "Info";
|
||||
type = types.enum [ "Info" "Debug" "Error" ];
|
||||
description = "Log level for gitea logging.";
|
||||
};
|
||||
|
||||
security = {
|
||||
secretKey = mkOption {
|
||||
type = types.str;
|
||||
description = "gitea secret key.";
|
||||
};
|
||||
|
||||
internalToken = mkOption {
|
||||
type = types.str;
|
||||
description = "gitea internal token.";
|
||||
};
|
||||
|
||||
installLock = mkOption {
|
||||
type = types.bool;
|
||||
description = "gitea install lock.";
|
||||
default = false; # TODO figure out what this actually does
|
||||
};
|
||||
|
||||
oauth2JwtSecret = mkOption {
|
||||
type = types.str;
|
||||
description = "OAuth2 JWT secret.";
|
||||
};
|
||||
};
|
||||
|
||||
database = {
|
||||
type = mkOption {
|
||||
type = types.enum [ "sqlite3" "mysql" "postgres" ];
|
||||
example = "mysql";
|
||||
default = "sqlite3";
|
||||
description = "Database engine to use.";
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "/data/gitea/gitea.db";
|
||||
description = "Database file path, if sqlite3 is in use";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Database host address";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = (if !usePostgresql then 3306 else pg.port);
|
||||
description = "Databa se host port.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "gitea";
|
||||
description = "Database user.";
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "Database password.";
|
||||
};
|
||||
|
||||
createDatabase = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to create a database automatically.";
|
||||
};
|
||||
};
|
||||
|
||||
ssh = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable external SSH feature.";
|
||||
};
|
||||
|
||||
clonePort = mkOption {
|
||||
type = types.int;
|
||||
default = 22;
|
||||
example = 2222;
|
||||
description = ''
|
||||
SSH port displayed in clone URL.
|
||||
The option is required to configure a service when the external visible port
|
||||
differs from the local listening port i.e. if port forwarding is used.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
lfs = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable git-lfs support.";
|
||||
};
|
||||
|
||||
contentDir = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.stateDir}/lfs";
|
||||
description = "Where to store LFS files.";
|
||||
};
|
||||
|
||||
lfsJwtSecret = mkOption {
|
||||
type = types.str;
|
||||
description = "LFS JWT Secret";
|
||||
};
|
||||
};
|
||||
|
||||
appName = mkOption {
|
||||
type = types.str;
|
||||
default = "gitea: Gitea Service";
|
||||
description = "Application name.";
|
||||
};
|
||||
|
||||
runMode = mkOption {
|
||||
type = types.enum [ "dev" "prod" "test" ];
|
||||
description = "run mode.";
|
||||
default = "prod";
|
||||
};
|
||||
|
||||
repositoryRoot = mkOption {
|
||||
type = types.str;
|
||||
default = # "${cfg.stateDir}/repositories"
|
||||
"";
|
||||
description = "Path to the git repositories.";
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
description = "Domain name of your server.";
|
||||
};
|
||||
|
||||
rootUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "http://localhost:3000/";
|
||||
description = "Full public URL of gitea server.";
|
||||
};
|
||||
|
||||
httpAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "HTTP listen address.";
|
||||
};
|
||||
|
||||
httpPort = mkOption {
|
||||
type = types.int;
|
||||
default = 3000;
|
||||
description = "HTTP listen port.";
|
||||
};
|
||||
|
||||
cookieSecure = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Marks session cookies as "secure" as a hint for browsers to only send
|
||||
them via HTTPS. This option is recommend, if gitea is being served over HTTPS.
|
||||
'';
|
||||
};
|
||||
|
||||
staticRootPath = mkOption {
|
||||
type = types.str;
|
||||
default = "\${pkgs.gitea.data}";
|
||||
example = "/var/lib/gitea/data";
|
||||
description = "Upper level of template and static files path.";
|
||||
};
|
||||
|
||||
disableRegistration = mkEnableOption "the registration lock" // {
|
||||
description = ''
|
||||
By default any user can create an account on this <literal>gitea</literal> instance.
|
||||
This can be disabled by using this option.
|
||||
<emphasis>Note:</emphasis> please keep in mind that this should be added after the initial
|
||||
deploy unless <link linkend="opt-services.gitea.useWizard">services.gitea.useWizard</link>
|
||||
is <literal>true</literal> as the first registered user will be the administrator if
|
||||
no install wizard is used.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (attrsOf (oneOf [ bool int str ]));
|
||||
default = {};
|
||||
description = ''
|
||||
Gitea configuration. Refer to <link xlink:href="https://docs.gitea.io/en-us/config-cheat-sheet/"/>
|
||||
for details on supported values.
|
||||
'';
|
||||
example = literalExample ''
|
||||
{
|
||||
"cron.sync_external_users" = {
|
||||
RUN_AT_START = true;
|
||||
SCHEDULE = "@every 24h";
|
||||
UPDATE_EXISTING = true;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
MAILER_TYPE = "sendmail";
|
||||
FROM = "do-not-reply@example.org";
|
||||
SENDMAIL_PATH = "''${pkgs.system-sendmail}/bin/sendmail";
|
||||
};
|
||||
other = {
|
||||
SHOW_FOOTER_VERSION = false;
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
settings = {
|
||||
database = mkMerge [
|
||||
{
|
||||
DB_TYPE = cfg.database.type;
|
||||
}
|
||||
(mkIf (useMysql || usePostgresql) {
|
||||
HOST = cfg.database.host + ":" + toString cfg.database.port;
|
||||
NAME = cfg.database.name;
|
||||
USER = cfg.database.user;
|
||||
PASSWD = cfg.database.password;
|
||||
})
|
||||
(mkIf useSqlite {
|
||||
PATH = cfg.database.path;
|
||||
})
|
||||
(mkIf usePostgresql {
|
||||
SSL_MODE = "disable";
|
||||
})
|
||||
];
|
||||
|
||||
repository = {
|
||||
ROOT = cfg.repositoryRoot;
|
||||
};
|
||||
|
||||
server = mkMerge [
|
||||
{
|
||||
DOMAIN = cfg.domain;
|
||||
# STATIC_ROOT_PATH = cfg.staticRootPath;
|
||||
LFS_JWT_SECRET = cfg.lfs.lfsJwtSecret;
|
||||
|
||||
HTTP_ADDR = cfg.httpAddress;
|
||||
HTTP_PORT = cfg.httpPort;
|
||||
}
|
||||
(mkIf cfg.ssh.enable {
|
||||
DISABLE_SSH = false;
|
||||
SSH_PORT = cfg.ssh.clonePort;
|
||||
})
|
||||
(mkIf (!cfg.ssh.enable) {
|
||||
DISABLE_SSH = true;
|
||||
})
|
||||
(mkIf cfg.lfs.enable {
|
||||
LFS_START_SERVER = true;
|
||||
LFS_CONTENT_PATH = cfg.lfs.contentDir;
|
||||
})
|
||||
];
|
||||
|
||||
session = {
|
||||
COOKIE_NAME = "session";
|
||||
COOKIE_SECURE = cfg.cookieSecure;
|
||||
};
|
||||
|
||||
security = with cfg.security; {
|
||||
SECRET_KEY = secretKey;
|
||||
INTERNAL_TOKEN = internalToken;
|
||||
INSTALL_LOCK = installLock;
|
||||
};
|
||||
|
||||
log = {
|
||||
ROUTER = "console";
|
||||
ROUTER_LOG_LEVEL = cfg.logLevel;
|
||||
};
|
||||
|
||||
service = {
|
||||
DISABLE_REGISTRATION = cfg.disableRegistration;
|
||||
};
|
||||
|
||||
oauth2 = {
|
||||
JWT_SECRET = cfg.security.oauth2JwtSecret;
|
||||
};
|
||||
};
|
||||
|
||||
run =
|
||||
let
|
||||
appIni = pkgs.writeText "app.ini" ''
|
||||
APP_NAME=${cfg.appName}
|
||||
RUN_USER=gitea
|
||||
RUN_MODE=${cfg.runMode}
|
||||
|
||||
${generators.toINI {} cfg.settings}
|
||||
'';
|
||||
in pkgs.writeShellScriptBin "run" ''
|
||||
export GITEA_WORK_FIR=${cfg.stateDir}
|
||||
exec /bin/gitea -c ${appIni}
|
||||
'';
|
||||
|
||||
};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
/nix/store/6cg3m50cm7jz6k308vab9p8pqxz27pfn-gitea.sh
|
|
@ -1,16 +0,0 @@
|
|||
let
|
||||
nixpkgs = import <nixpkgs> { system = "x86_64-linux"; };
|
||||
eval = nixpkgs.lib.evalModules {
|
||||
modules =
|
||||
[ (import /module.nix) ] ++
|
||||
(if (builtins.pathExists /config.nix) then [ (import /config.nix) ] else []);
|
||||
|
||||
args = {
|
||||
pkgs = nixpkgs;
|
||||
lib = nixpkgs.lib;
|
||||
};
|
||||
};
|
||||
in
|
||||
eval.config.run
|
||||
|
||||
# export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
|
26
docker/mariadb/default.nix
Normal file
26
docker/mariadb/default.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{ pkgs, system, nixpkgs, nixpkgs-unstable, ... }:
|
||||
let
|
||||
bashLib = ../bash-lib;
|
||||
init = pkgs.writeShellScriptBin "init" (builtins.readFile ./init);
|
||||
conf = pkgs.writeText "conf" ''
|
||||
_prog_busybox="${pkgs.busybox}"
|
||||
_prog_bashlib="${bashLib}"
|
||||
_prog_bash="${pkgs.bash}"
|
||||
_prog_mariadb="${(import nixpkgs-unstable { inherit system; }).mariadb}"
|
||||
_prog_nettools="${pkgs.nettools}"
|
||||
|
||||
_conf_user_uid="5000"
|
||||
_conf_user_gid="5000"
|
||||
_conf_data="/data/mariadb"
|
||||
|
||||
_file_mariadb_conf=${./mariadb.cnf}
|
||||
'';
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
name = "mariadb";
|
||||
tag = "latest";
|
||||
|
||||
config = {
|
||||
Entrypoint = [ "${init}/bin/init" "${conf}" ];
|
||||
};
|
||||
}
|
68
docker/mariadb/init
Normal file
68
docker/mariadb/init
Normal file
|
@ -0,0 +1,68 @@
|
|||
# -*- mode: shell-script; -*-
|
||||
|
||||
if [[ ! -f /env ]]
|
||||
then
|
||||
conf=$1 ; shift 1
|
||||
source $conf
|
||||
else
|
||||
source /env || \
|
||||
echo_exit "Failed to source env!"
|
||||
source $conf
|
||||
fi
|
||||
|
||||
source $_prog_bashlib/main.bash
|
||||
|
||||
if [[ $($_prog_busybox/bin/id -u) = 0 ]] ; then
|
||||
|
||||
$_prog_busybox/bin/cat <<EOF
|
||||
### MariaDB Nix Image Manual
|
||||
##
|
||||
## USER_UID ? $_conf_user_uid - default user id
|
||||
## USER_GID ? $_conf_user_gid - default group id
|
||||
|
||||
### Place additional config files in \`/etc/mysql/mariadb.conf.d\`
|
||||
EOF
|
||||
|
||||
default_opt USER_UID "$_conf_user_uid"
|
||||
default_opt USER_GID "$_conf_user_gid"
|
||||
|
||||
$_prog_busybox/bin/cat <<EOF
|
||||
### Starting with options:
|
||||
## USER_UID = "$_user_uid"
|
||||
## USER_GID = "$_user_gid"
|
||||
EOF
|
||||
|
||||
(
|
||||
set -e
|
||||
echo "mariadb:x:$_user_uid:$_user_gid:MariaDB:$_conf_data:$_prog_bash/bin/bash" > /etc/passwd
|
||||
echo "mariadb:x:$_user_gid:" > /etc/group
|
||||
) || echo_exit "Failed to create user and group!"
|
||||
|
||||
mkdir_chown /tmp "$_user_uid" "$_user_gid"
|
||||
mkdir_chown /run/mysqld/ "$_user_uid" "$_user_gid"
|
||||
|
||||
mkdir_chown /etc/mysql 0 0
|
||||
mkdir_chown /etc/mysql/mariadb.conf.d 0 0
|
||||
$_prog_busybox/bin/ln -s "$_file_mariadb_conf" /etc/mysql/my.cnf
|
||||
|
||||
[[ ! -d $_conf_data ]] && (mkdir_chown $_conf_data "$_user_uid" "$_user_gid" || echo_exit "Failed to create \`$_conf_data\`")
|
||||
|
||||
if [[ ! -d $_conf_data/mysql ]]
|
||||
then
|
||||
PATH=$_prog_busybox/bin:$_prog_nettools/bin $_prog_mariadb/bin/mysql_install_db --user=mariadb --datadir=$_conf_data --defaults-file=/etc/mysql/my.cnf
|
||||
fi
|
||||
|
||||
check_owner "$_conf_data" "$_user_uid" "$_user_gid"
|
||||
save_env "_user_uid \
|
||||
_user_gid \
|
||||
conf
|
||||
" > /env
|
||||
|
||||
check_root "$_user_uid"
|
||||
exec $_prog_busybox/bin/su mariadb -c "$0 $@" || /
|
||||
echo_exit "Failed to switch user!"
|
||||
else
|
||||
echo
|
||||
echo "Starting MariaDB!"
|
||||
$_prog_mariadb/bin/mysqld $@
|
||||
fi
|
23
docker/mariadb/mariadb.cnf
Normal file
23
docker/mariadb/mariadb.cnf
Normal file
|
@ -0,0 +1,23 @@
|
|||
# The MariaDB configuration file
|
||||
#
|
||||
# The MariaDB/MySQL tools read configuration files in the following order:
|
||||
# 1. "/etc/mysql/mariadb.cnf" (this file) to set global defaults,
|
||||
# 2. "/etc/mysql/conf.d/*.cnf" to set global options.
|
||||
# 3. "/etc/mysql/mariadb.conf.d/*.cnf" to set MariaDB-only options.
|
||||
# 4. "~/.my.cnf" to set user-specific options.
|
||||
#
|
||||
# If the same option is defined multiple times, the last one will apply.
|
||||
#
|
||||
# One can use all long options that the program supports.
|
||||
# Run program with --help to get a list of available options and with
|
||||
# --print-defaults to see which it would actually understand and use.
|
||||
|
||||
#
|
||||
# This group is read both both by the client and the server
|
||||
# use it for options that affect everything
|
||||
#
|
||||
[client-server]
|
||||
datadir=/data/mariadb
|
||||
|
||||
# Import all .cnf files from configuration directory
|
||||
!includedir /etc/mysql/mariadb.conf.d/
|
|
@ -1,39 +0,0 @@
|
|||
{ pkgs, nixpkgs, ... }:
|
||||
let
|
||||
env = let
|
||||
defaults = {
|
||||
user = "postgres";
|
||||
db = "postgres";
|
||||
host_auth_method = "scram-sha-256";
|
||||
data = "/pgdata";
|
||||
waldir = "/waldir";
|
||||
uid = builtins.toString 5000;
|
||||
gid = builtins.toString 5000;
|
||||
};
|
||||
postgres = pkgs.postgresql_12;
|
||||
bashLib = ../bash-lib;
|
||||
in
|
||||
with pkgs; with defaults; pkgs.writeShellScriptBin "conf" ''
|
||||
_conf_user=${user};
|
||||
_conf_database=${db};
|
||||
_conf_host_auth_method=${host_auth_method}
|
||||
_conf_data=${data}
|
||||
_conf_waldir=${waldir}
|
||||
_conf_user_uid=${uid}
|
||||
_conf_user_gid=${gid}
|
||||
|
||||
_prog_busybox=${busybox}
|
||||
_prog_postgres=${postgres}
|
||||
_prog_bash=${bash}
|
||||
_prog_bash_lib=${bashLib}
|
||||
'';
|
||||
init = pkgs.writeShellScript "init" (builtins.readFile ./init);
|
||||
in
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
name = "postgresql";
|
||||
tag = "latest";
|
||||
|
||||
config = {
|
||||
Cmd = [ "${init}" "${env}/bin/conf" ];
|
||||
};
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
# -*- mode: shell-script; -*-
|
||||
|
||||
conf=$1
|
||||
source $conf
|
||||
|
||||
source $_prog_bash_lib/main.bash
|
||||
|
||||
if [[ $(${_prog_busybox}/bin/id -u) = 0 ]] ; then
|
||||
${_prog_busybox}/bin/cat << EOF
|
||||
### PostgreSQL Nix Image MANUAL
|
||||
##
|
||||
## USER_UID ? $_conf_user_uid - default user id
|
||||
## USER_GID ? $_conf_user_gid - default group id
|
||||
## PASSWORD - password for POSTGRES_USER
|
||||
## DATABASE ? $_conf_database - default database
|
||||
## [ NO_CREATE_DB ] - disables the creation of a default user + db # Currently UNUSED !!
|
||||
## INITDB_ARGS ? "" - passed to \`initdb\`
|
||||
## [ INITDB_WALDIR ] ? $_conf_waldir - write-ahead log directory
|
||||
## HOST_AUTH_METHOD ? $_conf_host_auth_method - password authentication method
|
||||
## [ PG_HBA ] - overrides the creation of pg_hba.conf, if not set a default one is created
|
||||
## [ POSTGRES_CONF ] - postgres.conf file location for PostgreSQL
|
||||
## [ POSTGRES_CONF_OVERWRITE ] -
|
||||
## PGDATA ? $_conf_data - PostgreSQL data folder
|
||||
|
||||
### Recommended volumes (many directories which exist in normal Docker containers, do not exist in this one)
|
||||
##
|
||||
## - ${_conf_data} - PostgreSQL data folder
|
||||
## - ${_conf_waldir} - PostgreSQL waldir
|
||||
|
||||
EOF
|
||||
|
||||
_user_uid="${USER_UID:-${_conf_user_uid}}"
|
||||
_user_gid="${USER_GID:-${_conf_user_gid}}"
|
||||
|
||||
if [[ ! -z "${PASSWORD:-}" ]] ; then
|
||||
_password="$PASSWORD"
|
||||
else
|
||||
echo 'You must specify the `PASSWORD` parameter!' ; exit 1
|
||||
fi
|
||||
|
||||
_database="${DATABASE:-${_conf_database}}"
|
||||
_no_create_db="''${NO_CREATE_DB:-}"
|
||||
_initdb_args="''${INITDB_ARGS:-}"
|
||||
|
||||
if [[ ! -z "${INITDB_WALDIR+x}" ]] ; then
|
||||
_initdb_waldir="''${INITDB_WALDIR:-${_conf_waldir}}"
|
||||
else
|
||||
_initdb_waldir=""
|
||||
fi
|
||||
|
||||
_host_auth_method="${HOST_AUTH_METHOD:-${_conf_host_auth_method}}"
|
||||
if [[ ! -z "${PG_HBA+x}" ]] ; then
|
||||
if [[ ! -z "${PG_HBA:-}" ]] ; then
|
||||
if [[ -f "$PG_HBA" ]] ; then
|
||||
export _pg_hba="$PG_HBA"
|
||||
else
|
||||
echo "FILE \"$PG_HBA\" specified in \`PG_HBA'\ does not exist!" ; exit 1
|
||||
fi
|
||||
else
|
||||
echo 'Parameter `PG_HBA` is set, but empty!' ; exit 1
|
||||
fi
|
||||
else
|
||||
_pg_hba=""
|
||||
fi
|
||||
|
||||
export _pgdata="${PGDATA:-${_conf_data}}"
|
||||
|
||||
${_prog_busybox}/bin/cat << EOF
|
||||
## Starting with options:
|
||||
## USER_UID = "$_user_uid"
|
||||
## USER_GID = "$_user_gid"
|
||||
## USER = "$_conf_user"
|
||||
## PASSWORD = <REDACTED>
|
||||
## DATABASE = "$_database"
|
||||
## NO_CREATE_DB = "$([[ ! -z "$_no_create_db" ]] && echo true || echo false)"
|
||||
## INITDB_ARGS = "$_initdb_args"
|
||||
## INITDB_WALDIR = "$([[ ! -z "$_initdb_waldir" ]] && echo $_initdb_waldir || echo null)"
|
||||
## HOST_AUTH_METHOD = "$_host_auth_method"
|
||||
## PG_HBA = "$([[ ! -z "$_pg_hba" ]] && echo $_pg_hba || echo null)"
|
||||
## PGDATA="$_pgdata"
|
||||
EOF
|
||||
|
||||
echo "$_conf_user:x:$_user_uid:$_user_gid:PostgreSQL:$_pgdata:${_prog_bash}/bin/bash" > /etc/passwd
|
||||
echo "$_conf_user:x:$_user_gid:" > /etc/group
|
||||
|
||||
if [[ ! -d "$_pgdata" ]] ; then
|
||||
(
|
||||
set -e
|
||||
echo "Creating \`PGDATA\` and chown-ing to \"$_user_uid:$_user_gid\""
|
||||
${_prog_busybox}/bin/mkdir -p "$_pgdata"
|
||||
${_prog_busybox}/bin/chown postgres:postgres "$_pgdata"
|
||||
) || \
|
||||
echo_exit "Failed to create PGDATA!"
|
||||
else
|
||||
_pgdata_uid=$(${_prog_busybox}/bin/stat -c "%u" "$_pgdata" || \
|
||||
echo_exit "Failed to get uid of PGDATA!")
|
||||
_pgdata_gid=$(${_prog_busybox}/bin/stat -c "%g" "$_pgdata" || \
|
||||
echo_exit "Failed to get gid of PGDATA!")
|
||||
|
||||
if [[ $_pgdata_uid != $_user_uid ]] || [[ $_pgdata_gid != $_user_gid ]] ; then
|
||||
echo_exit \
|
||||
"\`PGDATA\` already exists but has incorrect owner! \
|
||||
$_pgdata_uid:$_pgdata_gid"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -s "$_pgdata/PG_VERSION" ]] ; then
|
||||
_database_exists="true"
|
||||
else
|
||||
_database_exists=""
|
||||
fi
|
||||
|
||||
if [[ ! -z "$_initdb_waldir" ]] ; then
|
||||
if [[ ! -d "$_initdb_waldir" ]] ; then
|
||||
(
|
||||
set -e
|
||||
echo "Creating \`INITDB_WALDIR\` and chown-ing to \"$_user_uid:$_user_gid\""
|
||||
${busybox}/bin/mkdir -p "$_initdb_waldir"
|
||||
${busybox}/bin/chown postgres:postgres "$_postgres_initdb_waldir"
|
||||
) || \
|
||||
echo_exit "Failed to create INITDB_WALDIR!"
|
||||
else
|
||||
_waldir_uid=$(${busybox}/bin/stat -c "%U" "$_postgres_initdb_waldir" || \
|
||||
echo_exit "Faile to get uid of INITDB_WALDIR")
|
||||
_waldir_gid=$(${busybox}/bin/stat -c "%G" "$_postgres_initdb_waldir" || \
|
||||
echo_exit "Faile to get gid of INITDB_WALDIR")
|
||||
|
||||
if [[ $_waldir_uid != $_user_uid ]] || [[ $_waldir_gid != $_user_gid ]] ; then
|
||||
echo_exit \
|
||||
"\`INITDB_WALDIR\` already exists but has incorrect owner! \
|
||||
$_waldir_uid:$_waldir_gid"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
$_prog_busybox/bin/mkdir -p /tmp /bin /run/postgresql || \
|
||||
echo_exit "Failed to create necessary directories!"
|
||||
$_prog_busybox/bin/chown postgres:postgres /tmp /run/postgresql || \
|
||||
echo_exit "Failed to chown directories!"
|
||||
|
||||
## Required due to popen failing with `Cannot allocate memory` of all things
|
||||
$_prog_busybox/bin/ln -s ${_prog_busybox}/bin/sh /bin/sh || \
|
||||
echo_exit "Failed to symlink /bin/sh!"
|
||||
|
||||
save_env "_conf_user \
|
||||
_pgdata \
|
||||
_database \
|
||||
_password \
|
||||
_pg_hba \
|
||||
_initdb_waldir \
|
||||
_initdb_args \
|
||||
_host_auth_method \
|
||||
_prog_postgres" > /env
|
||||
|
||||
exec $_prog_busybox/bin/su postgres -c "$0 $@" || \
|
||||
echo_exit "Failed to switch user!"
|
||||
else
|
||||
source /env || \
|
||||
echo_exit "Failed to source env!"
|
||||
|
||||
## Next 4 functions are "borrowed" straight from:
|
||||
## https://github.com/docker-library/postgres/blob/master/12/docker-entrypoint.sh
|
||||
## Thanks!
|
||||
# start socket-only postgresql server for setting up or running scripts
|
||||
# all arguments will be passed along as arguments to `postgres` (via pg_ctl)
|
||||
temp_server_start() {
|
||||
set -- "$@" -c listen_addresses="" -p "5432"
|
||||
|
||||
PGUSER="$_conf_user" \
|
||||
$_prog_postgres/bin/pg_ctl -D "$_pgdata" \
|
||||
-o "$(printf '%q ' "$@")" \
|
||||
-w start
|
||||
}
|
||||
|
||||
# stop postgresql server after done setting up user and running scripts
|
||||
temp_server_stop() {
|
||||
PGUSER="$_conf_user" \
|
||||
$_prog_postgres/bin/pg_ctl -D "$_pgdata" -m fast -w stop
|
||||
}
|
||||
|
||||
# Execute sql script, passed via stdin (or -f flag of pqsl)
|
||||
# usage: docker_process_sql [psql-cli-args]
|
||||
# ie: docker_process_sql --dbname=mydb <<<'INSERT ...'
|
||||
# ie: docker_process_sql -f my-file.sql
|
||||
# ie: docker_process_sql <my-file.sql
|
||||
process_sql() {
|
||||
local query_runner=( $_prog_postgres/bin/psql -v ON_ERROR_STOP=1 --username "$_conf_user" --no-password )
|
||||
if [ -n "$_database" ]; then
|
||||
query_runner+=( --dbname "$_database" )
|
||||
fi
|
||||
if [[ "$_host_auth_method" = "scram-sha-256" ]] ; then
|
||||
query_runner+=( --auth-host=scram-sha-256 )
|
||||
fi
|
||||
|
||||
"${query_runner[@]}" "$@"
|
||||
}
|
||||
|
||||
# create initial database
|
||||
# uses environment variables for input: POSTGRES_DB
|
||||
setup_db() {
|
||||
local dbAlreadyExists
|
||||
dbAlreadyExists="$(
|
||||
POSTGRES_DB= process_sql --dbname "$_database" --set db="$_database" --tuples-only <<-'EOSQL'
|
||||
SELECT 1 FROM pg_database WHERE datname = :'db' ;
|
||||
EOSQL
|
||||
)"
|
||||
if [ -z "$dbAlreadyExists" ]; then
|
||||
POSTGRES_DB= process_sql --dbname postgres --set db="$_database" <<-'EOSQL'
|
||||
CREATE DATABASE :"db" ;
|
||||
EOSQL
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ -z "${_database_exists:-}" ]] ; then
|
||||
$_prog_postgres/bin/initdb \
|
||||
--username="$_conf_user" \
|
||||
--pwfile=<(echo "$_password") \
|
||||
$([[ "$_initdb_waldir" != "null" ]] && echo "$_initdb_waldir") \
|
||||
$_initdb_args \
|
||||
--pgdata="$_pgdata"
|
||||
|
||||
export PGPASSWORD="$_password"
|
||||
temp_server_start
|
||||
|
||||
setup_db
|
||||
|
||||
temp_server_stop
|
||||
unset PGPASSWORD
|
||||
|
||||
if [[ -z "$_pg_hba" ]] ; then
|
||||
echo "host all all all $_host_auth_method" >> "$_pgdata/pg_hba.conf"
|
||||
else
|
||||
cp "$_pg_hba" "$_pgdata/pg_hba.conf"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Starting PostgreSQL"
|
||||
export PGDATA="$_pgdata"
|
||||
exec $_prog_postgres/bin/postgres
|
||||
fi
|
16
flake.lock
16
flake.lock
|
@ -63,12 +63,26 @@
|
|||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1613226215,
|
||||
"narHash": "sha256-3rA5cGIrBHD6yeKhNhsF7/t461ww25oJY8KyBb0IhjU=",
|
||||
"path": "/nix/store/nm00hhm641807yih5qxf98d9hxixzfg6-source",
|
||||
"rev": "ff96a0fa5635770390b184ae74debea75c3fd534",
|
||||
"type": "path"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"csi-driver-nfs": "csi-driver-nfs",
|
||||
"klippy": "klippy",
|
||||
"moonraker": "moonraker",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs";
|
||||
nixpkgs-unstable.url = "nixpkgs-unstable";
|
||||
|
||||
csi-driver-nfs = {
|
||||
flake = false;
|
||||
|
@ -39,6 +40,8 @@
|
|||
"postgresql"
|
||||
"gitea"
|
||||
"csi-driver-nfs"
|
||||
"nix"
|
||||
"mariadb"
|
||||
];
|
||||
containerTest = let
|
||||
all-modules = import <nixpkgs/nixos/modules/module-list.nix>;
|
||||
|
@ -52,9 +55,5 @@
|
|||
}).config.services.mysql.dataDir;
|
||||
in {
|
||||
inherit flakes dockerImages containerTest;
|
||||
|
||||
nginx-test = import ./infrastructure/nginx-test {
|
||||
inherit rlib inputs pkgs;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# -*- mode: conf; -*-
|
||||
|
||||
APP_NAME = Red Alder Gitea
|
||||
RUN_MODE = prod
|
||||
RUN_USER = gitea
|
||||
|
@ -9,7 +11,7 @@ ROOT = /data/gitea/git/repositories
|
|||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||||
|
||||
[repository.upload]
|
||||
TEMP_PATH = /data/gitea/uploads
|
||||
TEMP_PATH = /data/gitea/gitea/uploads
|
||||
|
||||
[server]
|
||||
APP_DATA_PATH = /data/gitea
|
||||
|
@ -21,44 +23,42 @@ SSH_PORT = 22
|
|||
SSH_LISTEN_PORT = 22
|
||||
LFS_START_SERVER = true
|
||||
LFS_CONTENT_PATH = /data/gitea/git/lfs
|
||||
DOMAIN = gitea.redalder.org
|
||||
DOMAIN = localhost
|
||||
LFS_JWT_SECRET = {{ with secret "kv/gitea" }}{{ .Data.lfs_jwt_secret }}{{ end }}
|
||||
OFFLINE_MODE = false
|
||||
|
||||
[database]
|
||||
PATH = /data/gitea/gitea.db
|
||||
DB_TYPE = postgres
|
||||
HOST = localhost
|
||||
POST = 5764
|
||||
DB_TYPE = mysql
|
||||
HOST = {{ env "NOMAD_HOST_ADDR_db" }}
|
||||
NAME = gitea
|
||||
USER = gitea
|
||||
PASSWD = gitea
|
||||
USER = {{ with secret "kv/gitea" }}{{ .Data.db_user }}{{ end }}
|
||||
PASSWD = {{ with secret "kv/gitea" }}{{ .Data.db_passwd }}{{ end }}
|
||||
SCHEMA =
|
||||
SSL_MODE = disable
|
||||
CHARSET = utf8
|
||||
|
||||
[indexer]
|
||||
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
||||
ISSUE_INDEXER_PATH = /data/gitea/gitea/indexers/issues.bleve
|
||||
REPO_INDEXER_PATH = /data/gitea/gitea/indexers/repos.bleve
|
||||
|
||||
[session]
|
||||
PROVIDER_CONFIG = /data/gitea/sessions
|
||||
PROVIDER_CONFIG = /data/gitea/gitea/sessions
|
||||
PROVIDER = file
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /data/gitea/avatars
|
||||
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
|
||||
AVATAR_UPLOAD_PATH = /data/gitea/gitea/avatars
|
||||
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/gitea/repo-avatars
|
||||
DISABLE_GRAVATAR = false
|
||||
ENABLE_FEDERATED_AVATAR = true
|
||||
|
||||
[attachment]
|
||||
PATH = /data/gitea/attachments
|
||||
|
||||
[log]
|
||||
ROOT_PATH = /data/gitea/log
|
||||
MODE = file
|
||||
LEVEL = info
|
||||
PATH = /data/gitea/gitea/attachments
|
||||
|
||||
[security]
|
||||
INSTALL_LOCK = true
|
||||
SECRET_KEY = {{ with secret "kv/gitea" }}{{ .Data.secret_key }}{{ end }}
|
||||
INTERNAL_TOKEN = {{ with secret "kv/gitea" }}{{ .Data.internal_token }}{{ end }}
|
||||
|
||||
[service]
|
||||
DISABLE_REGISTRATION = false
|
||||
|
@ -72,9 +72,12 @@ DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
|||
DEFAULT_ENABLE_TIMETRACKING = true
|
||||
NO_REPLY_ADDRESS = noreply.localhost
|
||||
|
||||
[oauth2]
|
||||
JWT_SECRET = {{ with secret "kv/gitea" }}{{ .Data.jwt_secret }}{{ end }}
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
|
||||
[openid]
|
||||
ENABLE_OPENID_SIGNIN = true
|
||||
ENABLE_OPENID_SIGNUP = true
|
||||
ENABLE_OPENID_SIGNUP = true
|
15
infrastructure/gitea/gitea-data.hcl
Normal file
15
infrastructure/gitea/gitea-data.hcl
Normal file
|
@ -0,0 +1,15 @@
|
|||
type = "csi"
|
||||
id = "gitea-data"
|
||||
name = "gitea-data"
|
||||
plugin_id = "nfs"
|
||||
access_mode = "single-node-writer"
|
||||
attachment_mode = "file-system"
|
||||
|
||||
context {
|
||||
server = "blowhole.in.redalder.org"
|
||||
share = "/gitea-data"
|
||||
}
|
||||
|
||||
mount_options {
|
||||
fs_type = "nfs"
|
||||
}
|
15
infrastructure/gitea/gitea-db.hcl
Normal file
15
infrastructure/gitea/gitea-db.hcl
Normal file
|
@ -0,0 +1,15 @@
|
|||
type = "csi"
|
||||
id = "gitea-db"
|
||||
name = "gitea-db"
|
||||
plugin_id = "nfs"
|
||||
access_mode = "single-node-writer"
|
||||
attachment_mode = "file-system"
|
||||
|
||||
context {
|
||||
server = "blowhole.in.redalder.org"
|
||||
share = "/gitea-db"
|
||||
}
|
||||
|
||||
mount_options {
|
||||
fs_type = "nfs"
|
||||
}
|
117
infrastructure/gitea/nomad.hcl
Normal file
117
infrastructure/gitea/nomad.hcl
Normal file
|
@ -0,0 +1,117 @@
|
|||
job "gitea" {
|
||||
datacenters = [ "homelab-1" ]
|
||||
type = "service"
|
||||
|
||||
group "svc" {
|
||||
count = 1
|
||||
|
||||
volume "gitea-data" {
|
||||
type = "csi"
|
||||
source = "gitea-data"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
volume "gitea-db" {
|
||||
type = "csi"
|
||||
source = "gitea-db"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
restart {
|
||||
attempts = 5
|
||||
delay = "5s"
|
||||
}
|
||||
|
||||
network {
|
||||
port "db" {
|
||||
to = "3306"
|
||||
}
|
||||
port "http" {
|
||||
static = "3666"
|
||||
to = "3000"
|
||||
}
|
||||
}
|
||||
|
||||
service {
|
||||
name = "gitea"
|
||||
port = "http"
|
||||
|
||||
check {
|
||||
type = "http"
|
||||
path = "/"
|
||||
interval = "2s"
|
||||
timeout = "2s"
|
||||
}
|
||||
}
|
||||
|
||||
task "app" {
|
||||
driver = "docker"
|
||||
|
||||
volume_mount {
|
||||
volume = "gitea-data"
|
||||
destination = "/data/gitea"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
config {
|
||||
image = "gitea:local"
|
||||
|
||||
ports = ["http"]
|
||||
|
||||
volumes = [
|
||||
"local/app.ini:/app.ini",
|
||||
]
|
||||
|
||||
labels = {
|
||||
"traefik.http.routers.gitea.rule" = "Host(`gitea.redalder.org`)"
|
||||
"traefik.http.services.gitea.loadbalancer.server.address" = "${NOMAD_HOST_ADDR_http}"
|
||||
"traefik.enable" = "true"
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
USER_UID = "5001"
|
||||
USER_GID = "5001"
|
||||
}
|
||||
|
||||
resources {
|
||||
cpu = 500
|
||||
memory = 1024
|
||||
}
|
||||
|
||||
vault {
|
||||
policies = ["gitea-policy"]
|
||||
}
|
||||
|
||||
template {
|
||||
data = file("./app.ini.tpl")
|
||||
destination = "local/app.ini"
|
||||
}
|
||||
}
|
||||
|
||||
task "db" {
|
||||
driver = "docker"
|
||||
|
||||
volume_mount {
|
||||
volume = "gitea-db"
|
||||
destination = "/data/mariadb"
|
||||
read_only = false
|
||||
}
|
||||
|
||||
config {
|
||||
image = "mariadb:local"
|
||||
ports = ["db"]
|
||||
}
|
||||
|
||||
env {
|
||||
USER_UID = "84"
|
||||
USER_GID = "84"
|
||||
}
|
||||
|
||||
resources {
|
||||
cpu = 500
|
||||
memory = 512
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{ pkgs, rlib, inputs }:
|
||||
let
|
||||
lockedNixpkgs =
|
||||
(builtins.fromJSON (builtins.readFile ../../flake.lock))
|
||||
.nodes.nixpkgs.locked;
|
||||
in
|
||||
rlib.substitute pkgs.runCommandNoCC "nginx-test.hcl" ./job.hcl {
|
||||
"nixpkgs.rev" = lockedNixpkgs.rev;
|
||||
"nixpkgs.sha" = lockedNixpkgs.narHash;
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
job "nginx-test" {
|
||||
datacenters = [ "homelab-1" ]
|
||||
type = "service"
|
||||
|
||||
group "nginx-test" {
|
||||
count = 1
|
||||
|
||||
network {
|
||||
port "http" {
|
||||
static = "8087"
|
||||
to = "80"
|
||||
}
|
||||
}
|
||||
|
||||
task "nix-prestart" {
|
||||
lifecycle {
|
||||
hook = "prestart"
|
||||
sidecar = false
|
||||
}
|
||||
|
||||
driver = "raw_exec"
|
||||
|
||||
template {
|
||||
data = <<EOF
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_profile_dir=/nix/var/nix/profiles/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}
|
||||
_gcroots_dir=/nix/var/nix/gcroots/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}
|
||||
|
||||
if [[ ! -d ${_profile_dir} ]]
|
||||
then
|
||||
mkdir -p "${_profile_dir}"
|
||||
else
|
||||
echo "${_profile_dir} exists when it shouldn't! Exiting..." ; exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d ${_gcroots} ]]
|
||||
then
|
||||
mkdir -p "${_gcroots_dir}"
|
||||
else
|
||||
echo "${_gcroots_dir} exists when it shouldn't! Exiting..." ; exit 1
|
||||
fi
|
||||
|
||||
/nix/var/nix/profiles/default/bin/nix-build "${NOMAD_TASK_DIR}/default.nix" -o "${_profile_dir}/system"
|
||||
|
||||
EOF
|
||||
destination = "/local/prepare.sh"
|
||||
}
|
||||
|
||||
template {
|
||||
data = <<EOF
|
||||
let
|
||||
nixpkgs = builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/tarball/@nixpkgs.rev@";
|
||||
sha256 = "@nixpkgs.sha@";
|
||||
};
|
||||
pkgs = import nixpkgs {};
|
||||
nixosSystem = import /nix/store/v61f12269zsqsliilpl0jqwg8xsvbvai-nixpkgs-21.03pre268117.64c12484642/nixpkgs/nixos;
|
||||
nspawn-init = pkgs.writeShellScriptBin "nspawn-init" ''
|
||||
${pkgs.bash}/bin/bash /nix/var/nix/profiles/system/activate
|
||||
exec /nix/var/nix/profiles/system/sw/bin/init
|
||||
'';
|
||||
in
|
||||
(nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
configuration = _: {
|
||||
boot.isContainer = true;
|
||||
time.timeZone = "Europe/Bratislava";
|
||||
|
||||
environment.systemPackages = [
|
||||
nspawn-init
|
||||
];
|
||||
|
||||
systemd.extraConfig = ''
|
||||
DefaultStandardOutput=tty
|
||||
'';
|
||||
|
||||
networking.firewall.enable = false;
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}).config.system.build.toplevel
|
||||
EOF
|
||||
destination = "/local/default.nix"
|
||||
}
|
||||
|
||||
config {
|
||||
command = "bash"
|
||||
args = [ "${NOMAD_TASK_DIR}/prepare.sh" ]
|
||||
}
|
||||
}
|
||||
|
||||
task "app" {
|
||||
driver = "nspawn"
|
||||
|
||||
config {
|
||||
image = "/nomad-nspawn-empty-dir"
|
||||
resolv_conf = "off"
|
||||
|
||||
ephemeral = true
|
||||
|
||||
bind_read_only = {
|
||||
"/nix/store" = "/nix/store"
|
||||
"/nix/var/nix/db" = "/nix/var/nix/db"
|
||||
"/nix/var/nix/daemon-socket" = "/nix/var/nix/daemon-socket"
|
||||
}
|
||||
|
||||
bind = {
|
||||
"/run/systemd/notify" = "/var/lib/provate/host-notify"
|
||||
"/nix/var/nix/profiles/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}":"/nix/var/nix/profiles"
|
||||
"/nix/var/nix/gcroots/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}":"/nix/var/nix/gcroots"
|
||||
}
|
||||
|
||||
user_namespacing = false
|
||||
boot = false
|
||||
|
||||
command = [
|
||||
"/nix/var/nix/profiles/system/sw/bin/bash",
|
||||
"/nix/var/nix/profiles/system/sw/bin/nspawn-init"
|
||||
]
|
||||
|
||||
ports = ["http"]
|
||||
}
|
||||
}
|
||||
|
||||
task "nix-poststop" {
|
||||
lifecycle {
|
||||
hook = "poststop"
|
||||
sidecar = false
|
||||
}
|
||||
|
||||
driver = "raw_exec"
|
||||
|
||||
template {
|
||||
data = <<EOF
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_profile_dir=/nix/var/nix/profiles/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}
|
||||
_gcroots_dir=/nix/var/nix/gcroots/nomad/${NOMAD_GROUP_NAME}-${NOMAD_ALLOC_INDEX}
|
||||
|
||||
if [[ -d ${_profile_dir} ]]
|
||||
then
|
||||
rm -r ${_profile_dir}
|
||||
else
|
||||
echo "${_profile_dir} does not exist! Exiting..." ; exit 1
|
||||
fi
|
||||
|
||||
if [[ -d ${_gcroots_dir} ]]
|
||||
then
|
||||
rm -r ${_gcroots_dir}
|
||||
else
|
||||
echo "${_gcroots_dir} does not exist! Exiting..." ; exit 1
|
||||
fi
|
||||
EOF
|
||||
destination = "/local/cleanup.sh"
|
||||
}
|
||||
|
||||
config {
|
||||
command = "bash"
|
||||
args = [ "${NOMAD_TASK_DIR}/cleanup.sh" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
[build]
|
||||
target = "x86_64-unknown-linux-musl"
|
14
nix-packages/rust-runner/.gitignore
vendored
14
nix-packages/rust-runner/.gitignore
vendored
|
@ -1,14 +0,0 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/rust
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
|
||||
|
||||
### Rust ###
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/rust
|
|
@ -1,17 +0,0 @@
|
|||
[package]
|
||||
name = "rust-runner"
|
||||
version = "0.1.0"
|
||||
authors = ["Magic_RB <magic_rb@redalder.org>"]
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "gitea"
|
||||
path = "src/gitea.rs"
|
||||
|
||||
[dependencies]
|
||||
toml = "0.5.8"
|
||||
serde = { version = "1.0.122", features = ["derive"] }
|
||||
nix = "0.19.1"
|
||||
simplelog = "0.9.0"
|
||||
log = "0.4.13"
|
||||
privdrop = "0.5.0"
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
|
||||
in
|
||||
{
|
||||
overlay = final: prev:
|
||||
with final; {
|
||||
rust-runner = rustPlatform.buildRustPackage rec {
|
||||
pname = "rust-runner";
|
||||
version = "0.1";
|
||||
|
||||
src = ./.;
|
||||
|
||||
buildType = "debug";
|
||||
|
||||
cargoSha256 = "Z/Q66St/Q/suG8BxJXNwevdPvTQJgGzmvgGeCzP01KY=";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
defaultPackage = forAllSystems (system: (import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlay ];
|
||||
}).rust-runner);
|
||||
};
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
extern crate log;
|
||||
extern crate nix;
|
||||
extern crate serde;
|
||||
extern crate simplelog;
|
||||
extern crate toml;
|
||||
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::File,
|
||||
io::Read,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use log::{error, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn mkdir_chown<S: AsRef<str>>(s: S, uid: u32, gid: u32) -> Result<(), String> {
|
||||
use nix::{
|
||||
dir::Dir,
|
||||
fcntl::OFlag,
|
||||
sys::stat::{stat, Mode},
|
||||
unistd::{chown, mkdir},
|
||||
unistd::{Gid, Uid},
|
||||
};
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
let s = s.as_ref();
|
||||
|
||||
if let Ok(_) = Dir::open(s, OFlag::empty(), Mode::empty()) {
|
||||
let stat = stat(s).map_err(|err| format!("Failed to stat: {} {}", s, err))?;
|
||||
|
||||
if stat.st_uid != uid || stat.st_gid != gid {
|
||||
warn!(
|
||||
"Directory {} exists, but has incorrect o/g: {}:{}, trying to chown...",
|
||||
s, uid, gid
|
||||
);
|
||||
chown(s, Some(Uid::from_raw(uid)), Some(Gid::from_raw(gid)))
|
||||
.map_err(|err| format!("Failed to chown: {}, {}", s, err))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
create_dir_all(s).map_err(|err| format!("Failed to mkdir: {} {}", s, err))?;
|
||||
chown(s, Some(Uid::from_raw(uid)), Some(Gid::from_raw(gid)))
|
||||
.map_err(|err| format!("Failed to chown: {} {}", s, err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_privileges<S: AsRef<str>>(user: S) -> Result<(), String> {
|
||||
use privdrop::PrivDrop;
|
||||
|
||||
let user = user.as_ref();
|
||||
|
||||
PrivDrop::default()
|
||||
.user(user)
|
||||
.group(user)
|
||||
.apply()
|
||||
.map_err(|err| format!("Failed to drop priviledges to {}:{} {}", user, user, err))
|
||||
}
|
||||
|
||||
fn adduser<S: AsRef<str>>(name: S, uid: u32, gid: u32, home: S, shell: S) -> Result<(), String> {
|
||||
use std::{fs::OpenOptions, io::Write};
|
||||
|
||||
let passwd = "/etc/passwd";
|
||||
let group = "/etc/group";
|
||||
let mut file = OpenOptions::new()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(passwd)
|
||||
.map_err(|_| format!("Cannot open: {}", passwd))?;
|
||||
|
||||
file.write_all(
|
||||
format!(
|
||||
"{}:x:{}:{}:User:{}:{}",
|
||||
name.as_ref(),
|
||||
uid,
|
||||
gid,
|
||||
home.as_ref(),
|
||||
shell.as_ref(),
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.map_err(|_| format!("Write to {} failed", passwd))?;
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(group)
|
||||
.map_err(|err| format!("Cannot open: {} {}", group, err))?;
|
||||
|
||||
file.write_all(format!("{}:x:{}:", name.as_ref(), gid,).as_bytes())
|
||||
.map_err(|err| format!("Write to {} failed {}", passwd, err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exec<S: AsRef<str>>(command: S, args: &[S]) -> Result<(), String> {
|
||||
use std::ffi::CString;
|
||||
use nix::unistd::execv;
|
||||
|
||||
let command = command.as_ref();
|
||||
let args = args.iter().map(|arg| arg.as_ref());
|
||||
let args = [command]
|
||||
.iter()
|
||||
.map(|command| *command)
|
||||
.chain(args)
|
||||
.map(|arg| CString::new(arg))
|
||||
.collect::<Result<Vec<CString>, _>>()
|
||||
.map_err(|err| format!("Failed to create CString {}", err))?;
|
||||
let command = CString::new(command).map_err(|err| format!("Failed to create CString {}", err))?;
|
||||
|
||||
execv(command.as_c_str(), args.as_ref()).map_err(|err| format!("execv failed {}", err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod defaults {
|
||||
pub fn uid() -> u32 {
|
||||
5000
|
||||
}
|
||||
pub fn gid() -> u32 {
|
||||
5000
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Configuration<'a> {
|
||||
#[serde(default = "defaults::uid")]
|
||||
gid: u32,
|
||||
#[serde(default = "defaults::gid")]
|
||||
uid: u32,
|
||||
app_ini: Option<&'a str>,
|
||||
app_ini_overwrite: bool,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
{
|
||||
use simplelog::{Config, LevelFilter, TermLogger, TerminalMode};
|
||||
TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed)
|
||||
};
|
||||
|
||||
let mut file = File::open("/config.toml").map_err(|err| format!("Failed to open config {}", err))?;
|
||||
let mut str = String::new();
|
||||
file.read_to_string(&mut str).map_err(|err| format!("Failed read config {}", err))?;
|
||||
|
||||
let config = toml::from_str::<Configuration>(str.as_str())?;
|
||||
|
||||
mkdir_chown("/tmp/", config.uid, config.gid)?;
|
||||
mkdir_chown("/data/gitea/", config.uid, config.gid)?;
|
||||
mkdir_chown("/etc/", 0, 0)?;
|
||||
|
||||
adduser("gitea", config.uid, config.gid, "/data/gitea/", "/bin/sh")?; // TODO /bin/sh doesn't exist, we need busybox
|
||||
|
||||
info!("Dropping privileges to config.uid:config.gid");
|
||||
drop_privileges("gitea")?;
|
||||
|
||||
if let Some(app_ini) = config.app_ini {
|
||||
use nix::sys::stat::stat;
|
||||
use std::fs::copy;
|
||||
|
||||
let stat = stat(app_ini);
|
||||
|
||||
if stat.is_err() {
|
||||
copy(app_ini, "/data/gitea/app.ini").map_err(|err| format!("Failed to copy app.ini {}", err))?;
|
||||
} else {
|
||||
if config.app_ini_overwrite {
|
||||
copy(app_ini, "/data/gitea/app.ini").map_err(|err| format!("Failed to copy app.ini {}", err))?;
|
||||
} else {
|
||||
error!("app.ini exists, but not overwriting!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::env::set_var;
|
||||
|
||||
set_var("HOME", "/data/gitea/");
|
||||
set_var("GITEA_WORK_DIR", "/data/gitea/");
|
||||
exec("/bin/gitea", &["-c", "/data/gitea/app.ini"])?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Reference in a new issue