Initial commit.
This commit is contained in:
commit
9f27e056d5
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
### Vim ###
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
Sessionx.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
### Rust ###
|
||||||
|
**/target
|
||||||
|
|
||||||
|
### Nix $$$
|
||||||
|
**/result
|
||||||
78
authentik.nix
Normal file
78
authentik.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST = "10.88.0.1";
|
||||||
|
AUTHENTIK_REDIS__HOST = "10.88.0.1";
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
networking.firewall.trustedInterfaces = [ "podman0" ];
|
||||||
|
services.postgresql = {
|
||||||
|
enableTCPIP = true;
|
||||||
|
ensureDatabases = ["authentik"];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "authentik";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
authentication = ''
|
||||||
|
host all all 10.88.0.0/16 md5
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
services.redis = {
|
||||||
|
servers.authentik = {
|
||||||
|
enable = true;
|
||||||
|
requirePassFile = "/var/secrets/redis-password";
|
||||||
|
port = 6379;
|
||||||
|
bind = "10.88.0.1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
virtualisation.podman.enable = true;
|
||||||
|
virtualisation.oci-containers.backend = "podman";
|
||||||
|
virtualisation.oci-containers.containers = {
|
||||||
|
authentik-server = {
|
||||||
|
image = "ghcr.io/goauthentik/server:2024.12.2";
|
||||||
|
cmd = [ "server" ];
|
||||||
|
inherit environment;
|
||||||
|
environmentFiles = [ "/opt/authentik.env" ];
|
||||||
|
ports = [ "10.88.0.1:9000:9000" ];
|
||||||
|
volumes = [
|
||||||
|
#"${dataDir}/media:/media"
|
||||||
|
#"${dataDir}/assets:/web/dist/extra:ro"
|
||||||
|
#"${dataDir}/templates:/templates"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
authentik-worker = {
|
||||||
|
image = "ghcr.io/goauthentik/server:2024.12.2";
|
||||||
|
cmd = [ "worker" ];
|
||||||
|
inherit environment;
|
||||||
|
environmentFiles = [ "/opt/authentik.env" ];
|
||||||
|
volumes = [
|
||||||
|
#"${dataDir}/media:/media"
|
||||||
|
#"${dataDir}/assets:/web/dist/extra:ro"
|
||||||
|
#"${dataDir}/templates:/templates"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
authentik-ldap = {
|
||||||
|
image = "ghcr.io/goauthentik/ldap:2024.12.2";
|
||||||
|
ports = [ "10.88.0.1:389:3389" "10.88.0.1:636:6636" ];
|
||||||
|
environment = {
|
||||||
|
AUTHENTIK_HOST = "https://auth.orga.cebula.camp";
|
||||||
|
};
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/authentik-ldap"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.nginx.virtualHosts."auth.orga.cebula.camp" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://10.88.0.1:9000/";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
191
configuration.nix
Normal file
191
configuration.nix
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
# Edit this configuration file to define what should be installed on
|
||||||
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||||
|
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[ # Include the results of the hardware scan.
|
||||||
|
./hardware-configuration.nix
|
||||||
|
#./identity.nix
|
||||||
|
./mailserver.nix
|
||||||
|
./nextcloud.nix
|
||||||
|
./authentik.nix
|
||||||
|
./forgejo.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|
||||||
|
networking.hostName = "szalotka";
|
||||||
|
networking.domain = "cebula.camp";
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.interfaces.enp1s0 = {
|
||||||
|
ipv4.addresses = [
|
||||||
|
{ address = "135.181.235.222"; prefixLength = 29; }
|
||||||
|
];
|
||||||
|
ipv6.addresses = [
|
||||||
|
{ address = "2a01:4f9:4a:4319:1337::14"; prefixLength = 80; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
networking.defaultGateway = "135.181.235.217";
|
||||||
|
networking.defaultGateway6 = "2a01:4f9:4a:4319:1337::1";
|
||||||
|
networking.nameservers = [
|
||||||
|
"8.8.8.8"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
|
# users.users.jane = {
|
||||||
|
# isNormalUser = true;
|
||||||
|
# extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||||
|
# };
|
||||||
|
|
||||||
|
users.users.root = {
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG599UildOrAq+LIOQjKqtGMwjgjIxozI1jtQQRKHtCP q3k@mimeomia"
|
||||||
|
"cert-authority ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPt2EXhvAwjMZ+5j8P0dCMaUdXeUQePeTv8tBdHXNly mewp"
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQb3YQoiYFZLKwvHYKbu1bMqzNeDCAszQhAe1+QI5SLDOotclyY/vFmOReZOsmyMFl71G2d7d+FbYNusUnNNjTxRYQ021tVc+RkMdLJaORRURmQfEFEKbai6QSFTwErXzuoIzyEPK0lbsQuGgqT9WaVnRzHJ2Q/4+qQbxAS34PuR5NqEkmn4G6LMo3OyJ5mwPkCj9lsqz4BcxRaMWFO3mNcwGDfSW+sqgc3E8N6LKrTpZq3ke7xacpQmcG5DU9VO+2QVPdltl9jWbs3gXjmF92YRNOuKPVfAOZBBsp8JOznfx8s9wDgs7RwPmDpjIAJEyoABqW5hlXfqRbTnfnMvuR informatic@InformaticPC"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOccFr7RFddSB5kdvYCIdCyKgD3X79mC90cMImqziTd9 radex@radpro"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
users.groups.ldap-access = {};
|
||||||
|
|
||||||
|
# users.ldap = {
|
||||||
|
# enable = true;
|
||||||
|
# loginPam = true;
|
||||||
|
# nsswitch = true;
|
||||||
|
# base = "ou=users,dc=cebula,dc=camp";
|
||||||
|
# server = "ldap://10.88.0.1:389/";
|
||||||
|
# timeLimit = 1;
|
||||||
|
# daemon.enable = true;
|
||||||
|
# bind = {
|
||||||
|
# distinguishedName = "cn=ldap-access,ou=users,dc=cebula,dc=camp";
|
||||||
|
# passwordFile = "/var/secrets/ldap-access";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
services.sssd = {
|
||||||
|
enable = true;
|
||||||
|
sshAuthorizedKeysIntegration = true;
|
||||||
|
config = let
|
||||||
|
baseDN = "dc=cebula,dc=camp";
|
||||||
|
serviceAccount = "ldap-access";
|
||||||
|
allowedGroup = "cn=orga-infra,ou=groups,${baseDN}";
|
||||||
|
in ''
|
||||||
|
[nss]
|
||||||
|
filter_groups = root
|
||||||
|
filter_users = root
|
||||||
|
reconnection_retries = 3
|
||||||
|
|
||||||
|
[sssd]
|
||||||
|
config_file_version = 2
|
||||||
|
reconnection_retries = 3
|
||||||
|
domains = LDAP
|
||||||
|
services = nss, pam, ssh
|
||||||
|
|
||||||
|
[pam]
|
||||||
|
reconnection_retries = 3
|
||||||
|
|
||||||
|
[domain/LDAP]
|
||||||
|
cache_credentials = True
|
||||||
|
id_provider = ldap
|
||||||
|
chpass_provider = ldap
|
||||||
|
auth_provider = ldap
|
||||||
|
access_provider = ldap
|
||||||
|
|
||||||
|
ldap_uri = ldaps://10.88.0.1/
|
||||||
|
ldap_tls_reqcert = allow
|
||||||
|
|
||||||
|
ldap_schema = rfc2307bis
|
||||||
|
ldap_search_base = ${baseDN}
|
||||||
|
ldap_user_search_base = ou=users,${baseDN}
|
||||||
|
ldap_group_search_base = ${baseDN}
|
||||||
|
ldap_user_ssh_public_key = sshPublicKey
|
||||||
|
|
||||||
|
ldap_user_object_class = user
|
||||||
|
ldap_user_name = cn
|
||||||
|
ldap_group_object_class = group
|
||||||
|
ldap_group_name = cn
|
||||||
|
|
||||||
|
ldap_default_bind_dn = cn=${serviceAccount},ou=users,${baseDN}
|
||||||
|
ldap_default_authtok = $LDAP_DEFAULT_AUTHTOK
|
||||||
|
ldap_access_filter = memberOf=${allowedGroup}
|
||||||
|
'';
|
||||||
|
environmentFile = "/var/secrets/sssd";
|
||||||
|
};
|
||||||
|
security.pam.services.sshd.makeHomeDir = true;
|
||||||
|
security.sudo.extraRules = [{
|
||||||
|
groups = ["orga-infra"];
|
||||||
|
commands = [{
|
||||||
|
command = "ALL";
|
||||||
|
options = [ "NOPASSWD" ];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
|
||||||
|
environment.variables.EDITOR = "vim";
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
wget rxvt-unicode-unwrapped.terminfo htop dstat
|
||||||
|
git
|
||||||
|
|
||||||
|
((vim_configurable.override { features = "normal"; }).customize {
|
||||||
|
name = "vim";
|
||||||
|
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
|
||||||
|
start = [ vim-nix nerdtree ];
|
||||||
|
};
|
||||||
|
vimrcConfig.customRC = ''
|
||||||
|
syntax on
|
||||||
|
set expandtab
|
||||||
|
set tabstop=4
|
||||||
|
set autoindent
|
||||||
|
set shiftwidth=4
|
||||||
|
set bs=2
|
||||||
|
|
||||||
|
autocmd FileType nix setlocal shiftwidth=2 tabstop=2
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.mtr.enable = true;
|
||||||
|
|
||||||
|
services.journald.extraConfig = ''
|
||||||
|
SystemMaxUse=2G
|
||||||
|
'';
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
ports = [ 2222 ];
|
||||||
|
};
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
};
|
||||||
|
security.acme = {
|
||||||
|
# TODO(q3k): change to @cebula.camp address.
|
||||||
|
email = "q3k@q3k.org";
|
||||||
|
acceptTerms = true;
|
||||||
|
};
|
||||||
|
# Limit nscd memory usage, as it sometimes just blows up and the OOMkiller
|
||||||
|
# sucks at picking it up.
|
||||||
|
systemd.services.nscd.serviceConfig.MemoryMax = "256M";
|
||||||
|
|
||||||
|
|
||||||
|
# Open ports in the firewall.
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
80 443 # http
|
||||||
|
2222 # host ssh
|
||||||
|
];
|
||||||
|
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||||
|
# Or disable the firewall altogether.
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
|
||||||
|
# This value determines the NixOS release from which the default
|
||||||
|
# settings for stateful data, like file locations and database versions
|
||||||
|
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||||
|
# this value at the release version of the first install of this system.
|
||||||
|
# Before changing this value read the documentation for this option
|
||||||
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
|
system.stateVersion = "20.09"; # Did you read the comment?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
16
encryptor/.gitignore
vendored
Normal file
16
encryptor/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
/target
|
||||||
|
|
||||||
|
|
||||||
|
# Added by cargo
|
||||||
|
#
|
||||||
|
# already existing elements were commented out
|
||||||
|
|
||||||
|
#/target
|
||||||
|
|
||||||
|
|
||||||
|
# Added by cargo
|
||||||
|
#
|
||||||
|
# already existing elements were commented out
|
||||||
|
|
||||||
|
#/target
|
||||||
|
Cargo.lock
|
||||||
6
encryptor/Cargo.toml
Normal file
6
encryptor/Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"encryptor",
|
||||||
|
"decryptor",
|
||||||
|
"common",
|
||||||
|
]
|
||||||
12
encryptor/common/Cargo.toml
Normal file
12
encryptor/common/Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "common"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
protobuf = "2"
|
||||||
|
secretbox = "0"
|
||||||
|
base64 = "0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
protobuf-codegen-pure = "2.3"
|
||||||
12
encryptor/common/build.rs
Normal file
12
encryptor/common/build.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
extern crate protobuf_codegen_pure;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
|
||||||
|
out_dir: "src/protos",
|
||||||
|
input: &["proto/smtp.proto"],
|
||||||
|
includes: &["proto"],
|
||||||
|
customize: protobuf_codegen_pure::Customize {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}).expect("protoc");
|
||||||
|
}
|
||||||
10
encryptor/common/proto/smtp.proto
Normal file
10
encryptor/common/proto/smtp.proto
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
package camp.cebula.smtp;
|
||||||
|
|
||||||
|
message SMTPSource {
|
||||||
|
message V1 {
|
||||||
|
int64 timestamp = 1;
|
||||||
|
string sender = 2;
|
||||||
|
};
|
||||||
|
bytes v1_encrypted = 1;
|
||||||
|
}
|
||||||
5
encryptor/common/src/lib.rs
Normal file
5
encryptor/common/src/lib.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod protos;
|
||||||
|
|
||||||
|
pub const KEY: &'static str = "thiYux7lohfit2queibee9engo1eiVoi";
|
||||||
|
pub const B64C: base64::Config = base64::Config::new(base64::CharacterSet::UrlSafe, false);
|
||||||
|
|
||||||
1
encryptor/common/src/protos/mod.rs
Normal file
1
encryptor/common/src/protos/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod smtp;
|
||||||
396
encryptor/common/src/protos/smtp.rs
Normal file
396
encryptor/common/src/protos/smtp.rs
Normal file
|
|
@ -0,0 +1,396 @@
|
||||||
|
// This file is generated by rust-protobuf 2.25.1. Do not edit
|
||||||
|
// @generated
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
|
||||||
|
#![allow(unused_attributes)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||||
|
|
||||||
|
#![allow(box_pointers)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(trivial_casts)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unused_results)]
|
||||||
|
//! Generated file from `smtp.proto`
|
||||||
|
|
||||||
|
/// Generated files are compatible only with the same version
|
||||||
|
/// of protobuf runtime.
|
||||||
|
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_1;
|
||||||
|
|
||||||
|
#[derive(PartialEq,Clone,Default)]
|
||||||
|
pub struct SMTPSource {
|
||||||
|
// message fields
|
||||||
|
pub v1_encrypted: ::std::vec::Vec<u8>,
|
||||||
|
// special fields
|
||||||
|
pub unknown_fields: ::protobuf::UnknownFields,
|
||||||
|
pub cached_size: ::protobuf::CachedSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ::std::default::Default for &'a SMTPSource {
|
||||||
|
fn default() -> &'a SMTPSource {
|
||||||
|
<SMTPSource as ::protobuf::Message>::default_instance()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SMTPSource {
|
||||||
|
pub fn new() -> SMTPSource {
|
||||||
|
::std::default::Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
// bytes v1_encrypted = 1;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_v1_encrypted(&self) -> &[u8] {
|
||||||
|
&self.v1_encrypted
|
||||||
|
}
|
||||||
|
pub fn clear_v1_encrypted(&mut self) {
|
||||||
|
self.v1_encrypted.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_v1_encrypted(&mut self, v: ::std::vec::Vec<u8>) {
|
||||||
|
self.v1_encrypted = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable pointer to the field.
|
||||||
|
// If field is not initialized, it is initialized with default value first.
|
||||||
|
pub fn mut_v1_encrypted(&mut self) -> &mut ::std::vec::Vec<u8> {
|
||||||
|
&mut self.v1_encrypted
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take field
|
||||||
|
pub fn take_v1_encrypted(&mut self) -> ::std::vec::Vec<u8> {
|
||||||
|
::std::mem::replace(&mut self.v1_encrypted, ::std::vec::Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Message for SMTPSource {
|
||||||
|
fn is_initialized(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
while !is.eof()? {
|
||||||
|
let (field_number, wire_type) = is.read_tag_unpack()?;
|
||||||
|
match field_number {
|
||||||
|
1 => {
|
||||||
|
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.v1_encrypted)?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute sizes of nested messages
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn compute_size(&self) -> u32 {
|
||||||
|
let mut my_size = 0;
|
||||||
|
if !self.v1_encrypted.is_empty() {
|
||||||
|
my_size += ::protobuf::rt::bytes_size(1, &self.v1_encrypted);
|
||||||
|
}
|
||||||
|
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||||
|
self.cached_size.set(my_size);
|
||||||
|
my_size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
if !self.v1_encrypted.is_empty() {
|
||||||
|
os.write_bytes(1, &self.v1_encrypted)?;
|
||||||
|
}
|
||||||
|
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cached_size(&self) -> u32 {
|
||||||
|
self.cached_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
|
||||||
|
&self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
|
||||||
|
&mut self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn (::std::any::Any) {
|
||||||
|
self as &dyn (::std::any::Any)
|
||||||
|
}
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
|
||||||
|
self as &mut dyn (::std::any::Any)
|
||||||
|
}
|
||||||
|
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
Self::descriptor_static()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new() -> SMTPSource {
|
||||||
|
SMTPSource::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
descriptor.get(|| {
|
||||||
|
let mut fields = ::std::vec::Vec::new();
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
|
||||||
|
"v1_encrypted",
|
||||||
|
|m: &SMTPSource| { &m.v1_encrypted },
|
||||||
|
|m: &mut SMTPSource| { &mut m.v1_encrypted },
|
||||||
|
));
|
||||||
|
::protobuf::reflect::MessageDescriptor::new_pb_name::<SMTPSource>(
|
||||||
|
"SMTPSource",
|
||||||
|
fields,
|
||||||
|
file_descriptor_proto()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_instance() -> &'static SMTPSource {
|
||||||
|
static instance: ::protobuf::rt::LazyV2<SMTPSource> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
instance.get(SMTPSource::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Clear for SMTPSource {
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.v1_encrypted.clear();
|
||||||
|
self.unknown_fields.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for SMTPSource {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
::protobuf::text_format::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::reflect::ProtobufValue for SMTPSource {
|
||||||
|
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||||
|
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq,Clone,Default)]
|
||||||
|
pub struct SMTPSource_V1 {
|
||||||
|
// message fields
|
||||||
|
pub timestamp: i64,
|
||||||
|
pub sender: ::std::string::String,
|
||||||
|
// special fields
|
||||||
|
pub unknown_fields: ::protobuf::UnknownFields,
|
||||||
|
pub cached_size: ::protobuf::CachedSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ::std::default::Default for &'a SMTPSource_V1 {
|
||||||
|
fn default() -> &'a SMTPSource_V1 {
|
||||||
|
<SMTPSource_V1 as ::protobuf::Message>::default_instance()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SMTPSource_V1 {
|
||||||
|
pub fn new() -> SMTPSource_V1 {
|
||||||
|
::std::default::Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
// int64 timestamp = 1;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_timestamp(&self) -> i64 {
|
||||||
|
self.timestamp
|
||||||
|
}
|
||||||
|
pub fn clear_timestamp(&mut self) {
|
||||||
|
self.timestamp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_timestamp(&mut self, v: i64) {
|
||||||
|
self.timestamp = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// string sender = 2;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_sender(&self) -> &str {
|
||||||
|
&self.sender
|
||||||
|
}
|
||||||
|
pub fn clear_sender(&mut self) {
|
||||||
|
self.sender.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Param is passed by value, moved
|
||||||
|
pub fn set_sender(&mut self, v: ::std::string::String) {
|
||||||
|
self.sender = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable pointer to the field.
|
||||||
|
// If field is not initialized, it is initialized with default value first.
|
||||||
|
pub fn mut_sender(&mut self) -> &mut ::std::string::String {
|
||||||
|
&mut self.sender
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take field
|
||||||
|
pub fn take_sender(&mut self) -> ::std::string::String {
|
||||||
|
::std::mem::replace(&mut self.sender, ::std::string::String::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Message for SMTPSource_V1 {
|
||||||
|
fn is_initialized(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
while !is.eof()? {
|
||||||
|
let (field_number, wire_type) = is.read_tag_unpack()?;
|
||||||
|
match field_number {
|
||||||
|
1 => {
|
||||||
|
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||||
|
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||||
|
}
|
||||||
|
let tmp = is.read_int64()?;
|
||||||
|
self.timestamp = tmp;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.sender)?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute sizes of nested messages
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn compute_size(&self) -> u32 {
|
||||||
|
let mut my_size = 0;
|
||||||
|
if self.timestamp != 0 {
|
||||||
|
my_size += ::protobuf::rt::value_size(1, self.timestamp, ::protobuf::wire_format::WireTypeVarint);
|
||||||
|
}
|
||||||
|
if !self.sender.is_empty() {
|
||||||
|
my_size += ::protobuf::rt::string_size(2, &self.sender);
|
||||||
|
}
|
||||||
|
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||||
|
self.cached_size.set(my_size);
|
||||||
|
my_size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||||
|
if self.timestamp != 0 {
|
||||||
|
os.write_int64(1, self.timestamp)?;
|
||||||
|
}
|
||||||
|
if !self.sender.is_empty() {
|
||||||
|
os.write_string(2, &self.sender)?;
|
||||||
|
}
|
||||||
|
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||||
|
::std::result::Result::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cached_size(&self) -> u32 {
|
||||||
|
self.cached_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
|
||||||
|
&self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
|
||||||
|
&mut self.unknown_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn (::std::any::Any) {
|
||||||
|
self as &dyn (::std::any::Any)
|
||||||
|
}
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
|
||||||
|
self as &mut dyn (::std::any::Any)
|
||||||
|
}
|
||||||
|
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
Self::descriptor_static()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new() -> SMTPSource_V1 {
|
||||||
|
SMTPSource_V1::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||||
|
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
descriptor.get(|| {
|
||||||
|
let mut fields = ::std::vec::Vec::new();
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>(
|
||||||
|
"timestamp",
|
||||||
|
|m: &SMTPSource_V1| { &m.timestamp },
|
||||||
|
|m: &mut SMTPSource_V1| { &mut m.timestamp },
|
||||||
|
));
|
||||||
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
|
||||||
|
"sender",
|
||||||
|
|m: &SMTPSource_V1| { &m.sender },
|
||||||
|
|m: &mut SMTPSource_V1| { &mut m.sender },
|
||||||
|
));
|
||||||
|
::protobuf::reflect::MessageDescriptor::new_pb_name::<SMTPSource_V1>(
|
||||||
|
"SMTPSource.V1",
|
||||||
|
fields,
|
||||||
|
file_descriptor_proto()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_instance() -> &'static SMTPSource_V1 {
|
||||||
|
static instance: ::protobuf::rt::LazyV2<SMTPSource_V1> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
instance.get(SMTPSource_V1::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::Clear for SMTPSource_V1 {
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.timestamp = 0;
|
||||||
|
self.sender.clear();
|
||||||
|
self.unknown_fields.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for SMTPSource_V1 {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
::protobuf::text_format::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::protobuf::reflect::ProtobufValue for SMTPSource_V1 {
|
||||||
|
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||||
|
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
|
\n\nsmtp.proto\x12\x10camp.cebula.smtp\"u\n\nSMTPSource\x12#\n\x0cv1_enc\
|
||||||
|
rypted\x18\x01\x20\x01(\x0cR\x0bv1EncryptedB\0\x1a@\n\x02V1\x12\x1e\n\tt\
|
||||||
|
imestamp\x18\x01\x20\x01(\x03R\ttimestampB\0\x12\x18\n\x06sender\x18\x02\
|
||||||
|
\x20\x01(\tR\x06senderB\0:\0:\0B\0b\x06proto3\
|
||||||
|
";
|
||||||
|
|
||||||
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
|
||||||
|
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
|
||||||
|
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
|
||||||
|
file_descriptor_proto_lazy.get(|| {
|
||||||
|
parse_descriptor_proto()
|
||||||
|
})
|
||||||
|
}
|
||||||
10
encryptor/decryptor/Cargo.toml
Normal file
10
encryptor/decryptor/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "decryptor"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { path = "../common" }
|
||||||
|
protobuf = "2"
|
||||||
|
secretbox = "0"
|
||||||
|
base64 = "0"
|
||||||
23
encryptor/decryptor/src/main.rs
Normal file
23
encryptor/decryptor/src/main.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use protobuf::Message;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use common::{protos,B64C,KEY};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut input = String::new();
|
||||||
|
std::io::stdin().read_to_string(&mut input).unwrap();
|
||||||
|
let input: String = input.split("\n").collect::<Vec<&str>>().join("").chars().filter(|c| !c.is_whitespace()).collect();
|
||||||
|
|
||||||
|
let s_bytes = base64::decode_config(input, B64C).expect("base64 decode");
|
||||||
|
let s = protos::smtp::SMTPSource::parse_from_bytes(&s_bytes).expect("deproto");
|
||||||
|
let v1_encrypted = s.get_v1_encrypted();
|
||||||
|
if v1_encrypted.len() == 0 {
|
||||||
|
println!("v1_encrypted not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let b = secretbox::SecretBox::new(KEY, secretbox::CipherType::Salsa20).unwrap();
|
||||||
|
let v1_bytes = b.easy_unseal(&v1_encrypted).expect("invalid encrypted data");
|
||||||
|
|
||||||
|
let v1 = protos::smtp::SMTPSource_V1::parse_from_bytes(&v1_bytes).expect("deproto v1");
|
||||||
|
println!("{:?}", v1);
|
||||||
|
}
|
||||||
14
encryptor/encryptor/Cargo.toml
Normal file
14
encryptor/encryptor/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "encryptor"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "encryptor"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { path = "../common" }
|
||||||
|
protobuf = "2"
|
||||||
|
secretbox = "0"
|
||||||
|
base64 = "0"
|
||||||
64
encryptor/encryptor/src/lib.rs
Normal file
64
encryptor/encryptor/src/lib.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use std::os::raw;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use protobuf::Message;
|
||||||
|
|
||||||
|
use common::{protos,B64C,KEY};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn string_copyn_function(
|
||||||
|
i: *const raw::c_char,
|
||||||
|
l: raw::c_int,
|
||||||
|
) -> *mut raw::c_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_result(yield_: *mut*const raw::c_char, s: String) {
|
||||||
|
let s: &str = s.as_str();
|
||||||
|
let ptr = s.as_ptr() as *const raw::c_char;
|
||||||
|
unsafe {
|
||||||
|
let copy = string_copyn_function(ptr, s.len() as i32);
|
||||||
|
*yield_ = copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn encryptor(yield_: *mut*const raw::c_char, argc: raw::c_int, argv: *const*const raw::c_char) -> raw::c_int {
|
||||||
|
if argc != 1 {
|
||||||
|
write_result(yield_, format!("wrong arg count (want one, got {})", argc));
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cstr = unsafe { std::ffi::CStr::from_ptr(*argv) };
|
||||||
|
let sender = match cstr.to_str() {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => {
|
||||||
|
write_result(yield_, "invalid unicode".to_string());
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i64;
|
||||||
|
|
||||||
|
let mut v1 = protos::smtp::SMTPSource_V1::new();
|
||||||
|
v1.set_timestamp(now);
|
||||||
|
v1.set_sender(sender.to_string());
|
||||||
|
let v1_bytes = v1.write_to_bytes().unwrap();
|
||||||
|
|
||||||
|
let b = secretbox::SecretBox::new(KEY, secretbox::CipherType::Salsa20).unwrap();
|
||||||
|
let v1_encrypted = b.easy_seal(&v1_bytes);
|
||||||
|
|
||||||
|
let mut s = protos::smtp::SMTPSource::new();
|
||||||
|
s.set_v1_encrypted(v1_encrypted);
|
||||||
|
let s_bytes = s.write_to_bytes().unwrap();
|
||||||
|
|
||||||
|
let s_base64 = base64::encode_config(s_bytes, B64C);
|
||||||
|
let wrapped = s_base64.chars()
|
||||||
|
.collect::<Vec<char>>()
|
||||||
|
.chunks(70)
|
||||||
|
.map(|c| c.iter().collect::<String>())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n ");
|
||||||
|
|
||||||
|
write_result(yield_, wrapped);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
67
forgejo.nix
Normal file
67
forgejo.nix
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
nixpkgs.overlays = [
|
||||||
|
(self: super: {
|
||||||
|
# Always add '@cebula.camp' to LDAP email attribute, so that we can set
|
||||||
|
# the attribute to 'cn'. We don't have any other way to get an
|
||||||
|
# @cebula.camp email address.
|
||||||
|
forgejo-lts = super.forgejo-lts.overrideAttrs (oa: {
|
||||||
|
patches = oa.patches ++ [
|
||||||
|
./forgejo/0001-bad-bad-not-good-patch-it-s-3-am-and-i-am-tired.patch
|
||||||
|
];
|
||||||
|
doCheck = false;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
lfs.enable = true;
|
||||||
|
settings = {
|
||||||
|
service = {
|
||||||
|
DISABLE_REGISTRATION = false;
|
||||||
|
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||||
|
ENABLE_NOTIFY_MAIL = false;
|
||||||
|
};
|
||||||
|
server = {
|
||||||
|
ROOT_URL = "https://git.orga.cebula.camp";
|
||||||
|
HTTP_PORT = 3001;
|
||||||
|
DOMAIN = "git.orga.cebula.camp";
|
||||||
|
START_SSH_SERVER = true;
|
||||||
|
SSH_PORT = 22;
|
||||||
|
SSH_LISTEN_PORT = 2223;
|
||||||
|
BUILTIN_SSH_SERVER_USER = "git";
|
||||||
|
};
|
||||||
|
oauth2_client = {
|
||||||
|
REGISTER_EMAIL_CONFIRM = false;
|
||||||
|
ENABLE_AUTO_REGISTRATION = true;
|
||||||
|
USERNAME = "nickname";
|
||||||
|
ACCOUNT_LINKING = "auto";
|
||||||
|
};
|
||||||
|
DEFAULT = {
|
||||||
|
APP_ANME = "CebulaGit";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#systemd.services.forgejo-secrets.script = ''
|
||||||
|
# ${pkgs.forgejo}/bin/gitea admin user create --username bofh --password dupa.8 --email q3k@q3k.org --admin --must-change-password=false
|
||||||
|
#'';
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."git.orga.cebula.camp" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://localhost:3001";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# redirect external port 22 to internal 2223
|
||||||
|
networking.firewall.allowedTCPPorts = [ 22 2223 ];
|
||||||
|
networking.firewall.extraCommands = ''
|
||||||
|
iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2223
|
||||||
|
'';
|
||||||
|
networking.firewall.extraStopCommands = ''
|
||||||
|
iptables -t nat -F PREROUTING
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
From 09949e09b153d14bffdd765d48394f046a0848ef Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serge Bazanski <q3k@q3k.org>
|
||||||
|
Date: Mon, 20 Jan 2025 02:58:07 +0100
|
||||||
|
Subject: [PATCH] bad bad not good patch it's 3 am and i am tired
|
||||||
|
|
||||||
|
---
|
||||||
|
services/auth/source/ldap/source_search.go | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/services/auth/source/ldap/source_search.go b/services/auth/source/ldap/source_search.go
|
||||||
|
index 2a61386ae1..aceefe53ad 100644
|
||||||
|
--- a/services/auth/source/ldap/source_search.go
|
||||||
|
+++ b/services/auth/source/ldap/source_search.go
|
||||||
|
@@ -362,7 +362,7 @@ func (source *Source) SearchEntry(name, passwd string, directBind bool) *SearchR
|
||||||
|
username := sr.Entries[0].GetAttributeValue(source.AttributeUsername)
|
||||||
|
firstname := sr.Entries[0].GetAttributeValue(source.AttributeName)
|
||||||
|
surname := sr.Entries[0].GetAttributeValue(source.AttributeSurname)
|
||||||
|
- mail := sr.Entries[0].GetAttributeValue(source.AttributeMail)
|
||||||
|
+ mail := sr.Entries[0].GetAttributeValue(source.AttributeMail) + "@cebula.camp"
|
||||||
|
|
||||||
|
if isAttributeSSHPublicKeySet {
|
||||||
|
sshPublicKey = sr.Entries[0].GetAttributeValues(source.AttributeSSHPublicKey)
|
||||||
|
@@ -490,7 +490,7 @@ func (source *Source) SearchEntries() ([]*SearchResult, error) {
|
||||||
|
Username: v.GetAttributeValue(source.AttributeUsername),
|
||||||
|
Name: v.GetAttributeValue(source.AttributeName),
|
||||||
|
Surname: v.GetAttributeValue(source.AttributeSurname),
|
||||||
|
- Mail: v.GetAttributeValue(source.AttributeMail),
|
||||||
|
+ Mail: v.GetAttributeValue(source.AttributeMail) + "@cebula.camp",
|
||||||
|
IsAdmin: checkAdmin(l, source, v.DN),
|
||||||
|
Groups: usersLdapGroups,
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.44.2
|
||||||
|
|
||||||
72
forgejo/signin_inner.tmpl
Normal file
72
forgejo/signin_inner.tmpl
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn)}}
|
||||||
|
{{template "base/alert" .}}
|
||||||
|
{{end}}
|
||||||
|
<h4 class="ui top attached header center">
|
||||||
|
{{if .LinkAccountMode}}
|
||||||
|
{{ctx.Locale.Tr "auth.oauth_signin_title"}}
|
||||||
|
{{else}}
|
||||||
|
{{ctx.Locale.Tr "auth.login_userpass"}}
|
||||||
|
{{end}}
|
||||||
|
</h4>
|
||||||
|
<div class="ui attached segment">
|
||||||
|
<form class="ui form tw-max-w-2xl tw-m-auto" action="{{.SignInLink}}" method="post">
|
||||||
|
{{.CsrfTokenHtml}}
|
||||||
|
<div class="tw-hidden">
|
||||||
|
<div class="required field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
|
||||||
|
<label for="user_name">{{ctx.Locale.Tr "home.uname_holder"}}</label>
|
||||||
|
<input id="user_name" type="text" name="user_name" value="{{.user_name}}" autofocus required>
|
||||||
|
</div>
|
||||||
|
{{if or (not .DisablePassword) .LinkAccountMode}}
|
||||||
|
<div class="required field {{if and (.Err_Password) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
|
||||||
|
<label for="password">{{ctx.Locale.Tr "password"}}</label>
|
||||||
|
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="current-password" required>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if not .LinkAccountMode}}
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label>{{ctx.Locale.Tr "auth.remember_me"}}</label>
|
||||||
|
<input name="remember" type="checkbox">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{template "user/auth/captcha" .}}
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<button class="ui primary button">
|
||||||
|
{{if .LinkAccountMode}}
|
||||||
|
{{ctx.Locale.Tr "auth.oauth_signin_submit"}}
|
||||||
|
{{else}}
|
||||||
|
{{ctx.Locale.Tr "sign_in"}}
|
||||||
|
{{end}}
|
||||||
|
</button>
|
||||||
|
<a href="{{AppSubUrl}}/user/forgot_password">{{ctx.Locale.Tr "auth.forgot_password"}}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if .ShowRegistrationButton}}
|
||||||
|
<div class="field">
|
||||||
|
<a href="{{AppSubUrl}}/user/sign_up">{{ctx.Locale.Tr "auth.sign_up_now"}}</a>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if .OAuth2Providers}}
|
||||||
|
<div class="divider divider-text">
|
||||||
|
{{ctx.Locale.Tr "sign_in_or"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="oauth2-login-navigator" class="tw-py-1">
|
||||||
|
<div class="tw-flex tw-flex-col tw-justify-center">
|
||||||
|
<div id="oauth2-login-navigator-inner" class="tw-flex tw-flex-col tw-flex-wrap tw-items-center tw-gap-2">
|
||||||
|
{{range $provider := .OAuth2Providers}}
|
||||||
|
<a class="{{$provider.Name}} ui button tw-flex tw-items-center tw-justify-center tw-py-2 tw-w-full oauth-login-link" href="{{AppSubUrl}}/user/oauth2/{{$provider.DisplayName}}">
|
||||||
|
{{$provider.IconHTML 28}}
|
||||||
|
{{ctx.Locale.Tr "sign_in_with_provider" $provider.DisplayName}}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
28
hardware-configuration.nix
Normal file
28
hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
|
# and may be overwritten by future invocations. Please make changes
|
||||||
|
# to /etc/nixos/configuration.nix instead.
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "virtio_pci" "sr_mod" "virtio_blk" ];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
|
fileSystems."/" =
|
||||||
|
{ device = "/dev/disk/by-uuid/32cb35b8-5b9e-41f7-888e-8b29be3e4c5e";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/boot" =
|
||||||
|
{ device = "/dev/disk/by-uuid/A74D-903F";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
|
swapDevices = [ ];
|
||||||
|
|
||||||
|
}
|
||||||
247
mailserver.nix
Normal file
247
mailserver.nix
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
{ config, pkgs, lib, ... }: let
|
||||||
|
|
||||||
|
aliases = lib.fix (self: {
|
||||||
|
postmaster = [ "q3k" ];
|
||||||
|
MAILER-DAEMON = self.postmaster;
|
||||||
|
|
||||||
|
security = self.postmaster;
|
||||||
|
nobody = self.postmaster;
|
||||||
|
usenet = self.postmaster;
|
||||||
|
uucp = self.postmaster;
|
||||||
|
webmaster = self.postmaster;
|
||||||
|
www = self.postmaster;
|
||||||
|
|
||||||
|
orga = [ "rheya" "mewp" "martyna" ];
|
||||||
|
cfp = [ "martyna" ];
|
||||||
|
conduct = [ "mewp" "q3k" ];
|
||||||
|
});
|
||||||
|
mkAlias = name: members: "${name}: ${lib.concatStringsSep ", " members}";
|
||||||
|
aliasFile = pkgs.writeTextFile {
|
||||||
|
name = "aliases";
|
||||||
|
text = lib.concatStringsSep "\n" (lib.mapAttrsToList mkAlias aliases);
|
||||||
|
};
|
||||||
|
acmeDir = config.security.acme.certs."mail.orga.cebula.camp".directory;
|
||||||
|
|
||||||
|
# Little tool to encrypt the SMTP source.
|
||||||
|
encryptor = pkgs.rustPlatform.buildRustPackage {
|
||||||
|
name = "encryptor";
|
||||||
|
src = ./encryptor;
|
||||||
|
#cargoSha256 = lib.fakeSha256;
|
||||||
|
cargoSha256 = "sha256:1ky42jssq3sk2a3lf29qc019bwj73rczcaqdjaick3nmz7yf1679";
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
security.acme.certs."mail.orga.cebula.camp" = {
|
||||||
|
group = "acme-mail";
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [ 25 587 143 993 465 ];
|
||||||
|
users.groups.acme-mail = {
|
||||||
|
members = [
|
||||||
|
config.services.nginx.user
|
||||||
|
config.services.dovecot2.user
|
||||||
|
config.services.exim.user
|
||||||
|
];
|
||||||
|
};
|
||||||
|
services.nginx.virtualHosts."mail.orga.cebula.camp" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
services.exim = {
|
||||||
|
enable = true;
|
||||||
|
package = (pkgs.exim.override { enableLDAP = true; }).overrideAttrs (oa: {
|
||||||
|
preBuild = ''
|
||||||
|
sed '
|
||||||
|
s:^# \(EXPAND_DLFUNC\)=.*:\1=yes:
|
||||||
|
s:^# \(EXTRALIBS_EXIM\)=.*:\1=-ldl -rdynamic -export-dynamic:
|
||||||
|
' -i Local/Makefile
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
config = ''
|
||||||
|
primary_hostname = szalotka.cebula.camp
|
||||||
|
domainlist local_domains = cebula.camp
|
||||||
|
hostlist relay_from_hosts = 127.0.0.1
|
||||||
|
qualify_domain = cebula.camp
|
||||||
|
|
||||||
|
acl_smtp_rcpt = acl_check_rcpt
|
||||||
|
acl_smtp_data = acl_check_data
|
||||||
|
|
||||||
|
tls_advertise_hosts = *
|
||||||
|
tls_certificate = ${acmeDir}/fullchain.pem
|
||||||
|
tls_privatekey = ${acmeDir}/key.pem
|
||||||
|
tls_on_connect_ports = 465
|
||||||
|
|
||||||
|
daemon_smtp_ports = 25 : 587 : 465
|
||||||
|
|
||||||
|
never_users = root
|
||||||
|
host_lookup = *
|
||||||
|
|
||||||
|
rfc1413_hosts = *
|
||||||
|
rfc1413_query_timeout = 5s
|
||||||
|
|
||||||
|
ignore_bounce_errors_after = 2d
|
||||||
|
timeout_frozen_after = 7d
|
||||||
|
|
||||||
|
begin acl
|
||||||
|
|
||||||
|
acl_check_rcpt:
|
||||||
|
accept hosts = :
|
||||||
|
control = dkim_disable_verify
|
||||||
|
|
||||||
|
deny message = Restricted characters in address
|
||||||
|
domains = +local_domains
|
||||||
|
local_parts = ^[.] : ^.*[@%!/|]
|
||||||
|
|
||||||
|
accept local_parts = postmaster
|
||||||
|
domains = +local_domains
|
||||||
|
|
||||||
|
require verify = sender
|
||||||
|
|
||||||
|
accept hosts = +relay_from_hosts
|
||||||
|
control = submission
|
||||||
|
control = dkim_disable_verify
|
||||||
|
|
||||||
|
accept authenticated = *
|
||||||
|
control = submission
|
||||||
|
control = dkim_disable_verify
|
||||||
|
|
||||||
|
require message = Relay not permitted
|
||||||
|
domains = +local_domains
|
||||||
|
|
||||||
|
require verify = recipient
|
||||||
|
|
||||||
|
accept
|
||||||
|
|
||||||
|
acl_check_data:
|
||||||
|
|
||||||
|
accept
|
||||||
|
|
||||||
|
begin routers
|
||||||
|
|
||||||
|
dnslookup:
|
||||||
|
driver = dnslookup
|
||||||
|
domains = ! +local_domains
|
||||||
|
transport = remote_smtp
|
||||||
|
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
|
||||||
|
headers_add = X-Cebulacamp-Smtp-Source: ''${dlfunc{${encryptor}/lib/libencryptor.so}{encryptor}{$sender_rcvhost}}
|
||||||
|
headers_remove = Received
|
||||||
|
no_more
|
||||||
|
|
||||||
|
aliases:
|
||||||
|
driver = redirect
|
||||||
|
allow_fail
|
||||||
|
allow_defer
|
||||||
|
data = ''${lookup{$local_part}lsearch{${aliasFile}} {$value@cebula.camp}}
|
||||||
|
|
||||||
|
ldap_user:
|
||||||
|
driver = redirect
|
||||||
|
data = ''${lookup ldap { user="cn=ldap-access,ou=users,dc=cebula,dc=camp" pass="''${readfile(/var/secrets/ldap-access)}" \
|
||||||
|
ldap://10.88.0.1:389/ou=users,dc=cebula,dc=camp?\
|
||||||
|
cn?sub?(cn=''${quote_ldap:$local_part})} {$value@$domain}}
|
||||||
|
cannot_route_message = Unknown address
|
||||||
|
more = false
|
||||||
|
|
||||||
|
localuser:
|
||||||
|
driver = accept
|
||||||
|
transport = local_delivery
|
||||||
|
|
||||||
|
begin transports
|
||||||
|
|
||||||
|
remote_smtp:
|
||||||
|
driver = smtp
|
||||||
|
|
||||||
|
local_delivery:
|
||||||
|
driver = lmtp
|
||||||
|
socket = /var/run/dovecot2/lmtp
|
||||||
|
batch_max = 200
|
||||||
|
rcpt_include_affixes
|
||||||
|
|
||||||
|
|
||||||
|
begin authenticators
|
||||||
|
|
||||||
|
PLAIN:
|
||||||
|
driver = plaintext
|
||||||
|
server_set_id = $auth2
|
||||||
|
server_prompts = :
|
||||||
|
server_advertise_condition = ''${if def:tls_cipher }
|
||||||
|
server_condition = ''${if and{{ \
|
||||||
|
!eq{}{$auth2} }{ \
|
||||||
|
ldapauth{\
|
||||||
|
user="cn=''${quote_ldap_dn:$auth2},ou=users,dc=cebula,dc=camp" \
|
||||||
|
pass=''${quote:$auth3} \
|
||||||
|
ldap://10.88.0.1/} }} }
|
||||||
|
|
||||||
|
LOGIN:
|
||||||
|
driver = plaintext
|
||||||
|
server_set_id = $auth1
|
||||||
|
server_prompts = <| Username: | Password:
|
||||||
|
server_advertise_condition = ''${if def:tls_cipher }
|
||||||
|
server_condition = ''${if and{{ \
|
||||||
|
!eq{}{$auth1} }{ \
|
||||||
|
ldapauth{\
|
||||||
|
user="cn=''${quote_ldap_dn:$auth1},ou=users,dc=cebula,dc=camp" \
|
||||||
|
pass=''${quote:$auth2} \
|
||||||
|
ldap://10.88.0.1/} }} }
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.dovecot2 = {
|
||||||
|
enable = true;
|
||||||
|
mailUser = "vmail";
|
||||||
|
mailGroup = "vmail";
|
||||||
|
createMailUser = true;
|
||||||
|
enableLmtp = true;
|
||||||
|
sslServerCert = "${acmeDir}/fullchain.pem";
|
||||||
|
sslServerKey = "${acmeDir}/key.pem";
|
||||||
|
enablePAM = false;
|
||||||
|
|
||||||
|
extraConfig = ''
|
||||||
|
userdb {
|
||||||
|
driver = ldap
|
||||||
|
args = /etc/dovecot/dovecot-users-ldap.conf.ext
|
||||||
|
}
|
||||||
|
passdb {
|
||||||
|
driver = ldap
|
||||||
|
args = /etc/dovecot/dovecot-pass-ldap.conf.ext
|
||||||
|
}
|
||||||
|
protocol lmtp {
|
||||||
|
auth_username_format = %n
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.dovecot2.preStart = ''
|
||||||
|
cat > /etc/dovecot/dovecot-users-ldap.conf.ext <<END
|
||||||
|
user_attrs = \\
|
||||||
|
=home=/var/mail/%{ldap:cn}, \\
|
||||||
|
=mail=maildir:/var/mail/%{ldap:cn}/Maildir
|
||||||
|
user_filter = (&(objectClass=inetOrgPerson)(cn=%u))
|
||||||
|
iterate_attrs = =user=%{ldap:cn}
|
||||||
|
iterate_filter = (objectClass=inetOrgPerson)
|
||||||
|
base = ou=users,dc=cebula,dc=camp
|
||||||
|
hosts = 10.88.0.1
|
||||||
|
dn = cn=ldap-access,ou=users,dc=cebula,dc=camp
|
||||||
|
dnpass = $(cat /var/secrets/ldap-access)
|
||||||
|
END
|
||||||
|
cat > /etc/dovecot/dovecot-pass-ldap.conf.ext <<END
|
||||||
|
auth_bind = yes
|
||||||
|
auth_bind_userdn = cn=%u,ou=users,dc=cebula,dc=camp
|
||||||
|
base = ou=users,dc=cebula,dc=camp
|
||||||
|
hosts = 10.88.0.1
|
||||||
|
dn = cn=ldap-access,ou=users,dc=cebula,dc=camp
|
||||||
|
dnpass = $(cat /var/secrets/ldap-access)
|
||||||
|
END
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.roundcube = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "mail.orga.cebula.camp";
|
||||||
|
extraConfig = ''
|
||||||
|
$config['default_host'] = 'tls://mail.orga.cebula.camp';
|
||||||
|
$config['smtp_server'] = 'tls://mail.orga.cebula.camp';
|
||||||
|
$config['mail_domain'] = 'cebula.camp';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.dovecot2.extraGroups = [ "ldap-access" ];
|
||||||
|
users.users.exim.extraGroups = [ "ldap-access" ];
|
||||||
|
}
|
||||||
128
nextcloud.nix
Normal file
128
nextcloud.nix
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "cloud.orga.cebula.camp";
|
||||||
|
package = pkgs.nextcloud30;
|
||||||
|
settings = {
|
||||||
|
overwriteprotocol = "https";
|
||||||
|
trusted_proxies = [ "127.0.0.1" ];
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbname = "nextcloud";
|
||||||
|
dbuser = "nextcloud";
|
||||||
|
dbhost = "/run/postgresql";
|
||||||
|
adminpassFile = "/opt/nextcloudpass";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."${config.services.nextcloud.hostName}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."office.orga.cebula.camp" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations = {
|
||||||
|
"^~ /browser" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"^~ /hosting/discovery" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"^~ /hosting/capabilities" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"~ ^/cool" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_read_timeout 36000s;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"^~ ^/(c|l)ool" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"^~ /lool/adminws" = {
|
||||||
|
proxyPass = "http://localhost:9980";
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_read_timeout 36000s;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = let
|
||||||
|
nc = config.services.nextcloud.config;
|
||||||
|
in {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_16;
|
||||||
|
ensureDatabases = [ nc.dbname ];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = nc.dbuser;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers.containers.collabora = {
|
||||||
|
image = "collabora/code:24.04.11.3.1";
|
||||||
|
ports = [ "127.0.0.1:9980:9980" ];
|
||||||
|
environment = {
|
||||||
|
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
|
||||||
|
domain = "office.orga.cebula.camp";
|
||||||
|
username = "admin";
|
||||||
|
};
|
||||||
|
environmentFiles = [
|
||||||
|
"/var/secrets/collabora-admin-password"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
#virtualisation.oci-containers.containers.office = {
|
||||||
|
# image = "onlyoffice/documentserver:6.4.1.45";
|
||||||
|
# ports = [ "127.0.0.1:8181:80" ];
|
||||||
|
# volumes = [
|
||||||
|
# "onlyoffice_logs:/var/log/onlyoffice"
|
||||||
|
# "onlyoffice_data:/var/www/onlyoffide/Data"
|
||||||
|
# "onlyoffice_cache:/var/lib/onlyoffice"
|
||||||
|
# "onlyoffice_db:/var/lib/postgresql"
|
||||||
|
# ];
|
||||||
|
# environment = let
|
||||||
|
# # Secret used to limit access to ONLYOFFICE from our nextcloud instance.
|
||||||
|
# # This doesn't give access to any documents, and is just a shared key to
|
||||||
|
# # ensure nothing but our nextcloud instance has access to the server.
|
||||||
|
# secretKey = "…";
|
||||||
|
# in {
|
||||||
|
# JWT_ENABLED = "true";
|
||||||
|
# JWT_SECRET = secretKey;
|
||||||
|
# };
|
||||||
|
#};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue