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:
|
{ pkgs, nixpkgs, ... }@inputs:
|
||||||
let
|
let
|
||||||
ldflags = "-s -w -extldflags '-static'";
|
|
||||||
csi-driver-nfs = pkgs.buildGoModule {
|
csi-driver-nfs = pkgs.buildGoModule {
|
||||||
name = "csi-driver-nfs";
|
name = "csi-driver-nfs";
|
||||||
version = "2.0";
|
version = "2.0";
|
||||||
|
@ -11,8 +10,10 @@ let
|
||||||
|
|
||||||
src = inputs.csi-driver-nfs;
|
src = inputs.csi-driver-nfs;
|
||||||
};
|
};
|
||||||
init = pkgs.writeShellScriptBin "init" ''
|
init = with pkgs; pkgs.writeShellScriptBin "init" ''
|
||||||
${csi-driver-nfs}/bin/nfsplugin $@
|
export "PATH=${busybox}/bin:$PATH"
|
||||||
|
echo $PATH
|
||||||
|
exec ${csi-driver-nfs}/bin/nfsplugin $@
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.dockerTools.buildLayeredImage {
|
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, ... }:
|
{ pkgs, system, nixpkgs, ... }:
|
||||||
let
|
let
|
||||||
# pkgs = (import nixpkgs { inherit system; }).pkgsMusl;
|
# pkgs = (import nixpkgs { inherit system; }).pkgsMusl;
|
||||||
contents = let
|
gitea =
|
||||||
defaults = {
|
let
|
||||||
userUid = builtins.toString 5001;
|
|
||||||
userGid = builtins.toString 5001;
|
|
||||||
user = "gitea";
|
|
||||||
data = "/data/gitea";
|
|
||||||
};
|
|
||||||
custom = rec {
|
|
||||||
gitea = pkgs.gitea.override {
|
|
||||||
inherit openssh git;
|
|
||||||
pamSupport = false;
|
|
||||||
};
|
|
||||||
openssh = pkgs.openssh.override {
|
openssh = pkgs.openssh.override {
|
||||||
withKerberos = false; withFIDO = false;
|
withKerberos = false; withFIDO = false;
|
||||||
};
|
};
|
||||||
|
@ -26,19 +16,29 @@ let
|
||||||
withpcre2 = false;
|
withpcre2 = false;
|
||||||
sendEmailSupport = false;
|
sendEmailSupport = false;
|
||||||
};
|
};
|
||||||
};
|
in
|
||||||
bashLib = ../bash-lib;
|
pkgs.gitea.override {
|
||||||
in
|
inherit openssh git;
|
||||||
pkgs.symlinkJoin { name = "contents"; paths = [ custom.gitea ]; };
|
pamSupport = false;
|
||||||
init = "${pkgs.rust-runner}/bin/gitea";
|
};
|
||||||
|
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
|
in
|
||||||
pkgs.dockerTools.buildLayeredImage {
|
pkgs.dockerTools.buildLayeredImage {
|
||||||
name = "gitea";
|
name = "gitea";
|
||||||
tag = "latest";
|
tag = "latest";
|
||||||
|
|
||||||
inherit contents;
|
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
Entrypoint = [ "${init}" ];
|
Entrypoint = [ "${init}/bin/init" "${conf}" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,5 @@ services:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: ./config.toml
|
source: $PWD/app.ini
|
||||||
target: /config.toml
|
|
||||||
- type: bind
|
|
||||||
source: ./config.toml
|
|
||||||
target: /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"
|
"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": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"csi-driver-nfs": "csi-driver-nfs",
|
"csi-driver-nfs": "csi-driver-nfs",
|
||||||
"klippy": "klippy",
|
"klippy": "klippy",
|
||||||
"moonraker": "moonraker",
|
"moonraker": "moonraker",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "nixpkgs";
|
nixpkgs.url = "nixpkgs";
|
||||||
|
nixpkgs-unstable.url = "nixpkgs-unstable";
|
||||||
|
|
||||||
csi-driver-nfs = {
|
csi-driver-nfs = {
|
||||||
flake = false;
|
flake = false;
|
||||||
|
@ -39,6 +40,8 @@
|
||||||
"postgresql"
|
"postgresql"
|
||||||
"gitea"
|
"gitea"
|
||||||
"csi-driver-nfs"
|
"csi-driver-nfs"
|
||||||
|
"nix"
|
||||||
|
"mariadb"
|
||||||
];
|
];
|
||||||
containerTest = let
|
containerTest = let
|
||||||
all-modules = import <nixpkgs/nixos/modules/module-list.nix>;
|
all-modules = import <nixpkgs/nixos/modules/module-list.nix>;
|
||||||
|
@ -52,9 +55,5 @@
|
||||||
}).config.services.mysql.dataDir;
|
}).config.services.mysql.dataDir;
|
||||||
in {
|
in {
|
||||||
inherit flakes dockerImages containerTest;
|
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
|
APP_NAME = Red Alder Gitea
|
||||||
RUN_MODE = prod
|
RUN_MODE = prod
|
||||||
RUN_USER = gitea
|
RUN_USER = gitea
|
||||||
|
@ -9,7 +11,7 @@ ROOT = /data/gitea/git/repositories
|
||||||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||||||
|
|
||||||
[repository.upload]
|
[repository.upload]
|
||||||
TEMP_PATH = /data/gitea/uploads
|
TEMP_PATH = /data/gitea/gitea/uploads
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
APP_DATA_PATH = /data/gitea
|
APP_DATA_PATH = /data/gitea
|
||||||
|
@ -21,44 +23,42 @@ SSH_PORT = 22
|
||||||
SSH_LISTEN_PORT = 22
|
SSH_LISTEN_PORT = 22
|
||||||
LFS_START_SERVER = true
|
LFS_START_SERVER = true
|
||||||
LFS_CONTENT_PATH = /data/gitea/git/lfs
|
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
|
OFFLINE_MODE = false
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
PATH = /data/gitea/gitea.db
|
PATH = /data/gitea/gitea.db
|
||||||
DB_TYPE = postgres
|
DB_TYPE = mysql
|
||||||
HOST = localhost
|
HOST = {{ env "NOMAD_HOST_ADDR_db" }}
|
||||||
POST = 5764
|
|
||||||
NAME = gitea
|
NAME = gitea
|
||||||
USER = gitea
|
USER = {{ with secret "kv/gitea" }}{{ .Data.db_user }}{{ end }}
|
||||||
PASSWD = gitea
|
PASSWD = {{ with secret "kv/gitea" }}{{ .Data.db_passwd }}{{ end }}
|
||||||
SCHEMA =
|
SCHEMA =
|
||||||
SSL_MODE = disable
|
SSL_MODE = disable
|
||||||
CHARSET = utf8
|
CHARSET = utf8
|
||||||
|
|
||||||
[indexer]
|
[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]
|
[session]
|
||||||
PROVIDER_CONFIG = /data/gitea/sessions
|
PROVIDER_CONFIG = /data/gitea/gitea/sessions
|
||||||
PROVIDER = file
|
PROVIDER = file
|
||||||
|
|
||||||
[picture]
|
[picture]
|
||||||
AVATAR_UPLOAD_PATH = /data/gitea/avatars
|
AVATAR_UPLOAD_PATH = /data/gitea/gitea/avatars
|
||||||
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
|
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/gitea/repo-avatars
|
||||||
DISABLE_GRAVATAR = false
|
DISABLE_GRAVATAR = false
|
||||||
ENABLE_FEDERATED_AVATAR = true
|
ENABLE_FEDERATED_AVATAR = true
|
||||||
|
|
||||||
[attachment]
|
[attachment]
|
||||||
PATH = /data/gitea/attachments
|
PATH = /data/gitea/gitea/attachments
|
||||||
|
|
||||||
[log]
|
|
||||||
ROOT_PATH = /data/gitea/log
|
|
||||||
MODE = file
|
|
||||||
LEVEL = info
|
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
|
SECRET_KEY = {{ with secret "kv/gitea" }}{{ .Data.secret_key }}{{ end }}
|
||||||
|
INTERNAL_TOKEN = {{ with secret "kv/gitea" }}{{ .Data.internal_token }}{{ end }}
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
DISABLE_REGISTRATION = false
|
DISABLE_REGISTRATION = false
|
||||||
|
@ -72,9 +72,12 @@ DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||||
DEFAULT_ENABLE_TIMETRACKING = true
|
DEFAULT_ENABLE_TIMETRACKING = true
|
||||||
NO_REPLY_ADDRESS = noreply.localhost
|
NO_REPLY_ADDRESS = noreply.localhost
|
||||||
|
|
||||||
|
[oauth2]
|
||||||
|
JWT_SECRET = {{ with secret "kv/gitea" }}{{ .Data.jwt_secret }}{{ end }}
|
||||||
|
|
||||||
[mailer]
|
[mailer]
|
||||||
ENABLED = false
|
ENABLED = false
|
||||||
|
|
||||||
[openid]
|
[openid]
|
||||||
ENABLE_OPENID_SIGNIN = true
|
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