Initial commit
Some checks failed
CI / check (push) Has been cancelled
CI / ida (push) Has been cancelled
CI / cpt (push) Has been cancelled
CI / build-nixos (ena) (push) Has been cancelled
CI / build-nixos (hako) (push) Has been cancelled
CI / build-nixos (kazusa) (push) Has been cancelled
CI / build-nixos (mizuki) (push) Has been cancelled

This commit is contained in:
암냥 2026-07-03 16:53:49 +09:00
commit 70284509f3
No known key found for this signature in database
144 changed files with 7061 additions and 0 deletions

View file

@ -0,0 +1,6 @@
creation_rules:
- path_regex: secrets/.*\.ya?ml$
age:
- age1mgels4hjl7l07gcnt72g86kvhrvd82fha9kuvlp46mpks7unrpmqvy959u # mizuki
- age1dcvh6q9953es9fvt8rq8rdgcktlt64asn2tf2y3vmyz0gntxzynqg2xgzk # hako
- age1hlsu7fdwwfm93rjt686j9cdy5klefwdus9jdxt5e0vaqh8c2la9qu5utns # kazusa

View file

@ -0,0 +1,103 @@
{
pkgs,
inputs,
lib,
...
}:
{
imports = [
"${inputs.self}/modules/nixos/base"
"${inputs.self}/modules/nixos/features/boot.nix"
"${inputs.self}/modules/nixos/features/ssh.nix"
"${inputs.self}/modules/nixos/features/docker.nix"
./services/mailserver.nix
./services/caddy.nix
];
# Override shared boot.nix for Legacy BIOS
boot.loader.grub.enableCryptodisk = lib.mkForce false;
services.netbird.enable = true;
users.users.imnyang.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOHP3Z+AYrRh9f8TYyqChKfeyNm3lOe0F75AwRHTTaxD imnyang@kazusa"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIrpjEYOBx7LTGb7QsPrmPBboqyTUNm/e+4+yqWruljv imnyang@natsu"
];
environment.systemPackages = with pkgs; [
eza
neovim
nil
nixd
bun
];
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1;
};
programs.git.config = {
safe.directory = "*";
};
networking = {
hostName = "kazusa";
domain = "icn.mizuki.guru";
nameservers = [
"1.1.1.1"
"1.0.0.1"
"9.9.9.9"
"149.112.112.112"
];
useDHCP = false;
dhcpcd.enable = false;
interfaces.ens18 = {
ipv4.addresses = [
{
address = "82.21.82.30";
prefixLength = 24;
}
];
};
defaultGateway = {
address = "82.21.82.1";
interface = "ens18";
};
};
networking.firewall.allowedTCPPorts = [
22
80
443
];
systemd.services.gnaynmi = {
description = "discord bot";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
User = "imnyang";
WorkingDirectory = "/home/imnyang/gnaynmi";
EnvironmentFile = "/home/imnyang/gnaynmi/.env";
ExecStart = "${pkgs.bun}/bin/bun run src/index.ts";
Restart = "always";
RestartSec = 5;
};
path = [
pkgs.bun
pkgs.stdenv.cc.cc.lib
];
environment = {
LD_LIBRARY_PATH = "${pkgs.stdenv.cc.cc.lib}/lib";
};
};
services.qemuGuest.enable = true;
system.stateVersion = "26.05";
}

View file

@ -0,0 +1,26 @@
{
inputs,
overlays,
}:
let
inherit (inputs) nixpkgs home-manager sops-nix;
in
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
sops-nix.nixosModules.sops
./configuration.nix
./hardware-configuration.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.imnyang = import ./home;
}
];
specialArgs = {
inherit inputs;
inherit overlays;
};
}

View file

@ -0,0 +1,45 @@
# 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"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/bfc62982-b6e4-43b9-99d7-951e7bcb1b31";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/0BA0-4E1A";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,77 @@
{
config,
pkgs,
inputs,
...
}:
let
nr = import "${inputs.self}/modules/nixos/features/packages/nr.nix" { inherit pkgs; };
nrr = import "${inputs.self}/modules/nixos/features/packages/nrr.nix" { inherit pkgs; };
in
{
home.stateVersion = "26.05";
home.username = "imnyang";
home.homeDirectory = "/home/imnyang";
home.packages = [
nr
nrr
];
home.sessionVariables = {
EDITOR = "nvim";
VISUAL = "nvim";
};
programs.fish = {
enable = true;
shellAliases = {
".." = "cd ..";
"..." = "cd ../..";
ls = "eza";
ll = "eza -l";
la = "eza -a";
lla = "eza -la";
rebuild = "sudo nixos-rebuild switch --flake .#natsu";
update = "nix flake update";
clean = "sudo nix-collect-garbage -d";
};
interactiveShellInit = ''
set -g fish_greeting ""
set -g fish_color_command blue
set -g fish_color_error red
set -g fish_color_param cyan
'';
};
programs.starship = {
enable = true;
settings = {
format = "$username@$hostname:$directory$character";
add_newline = false;
username = {
style_user = "purple";
style_root = "purple";
format = "[$user]($style)";
show_always = true;
};
hostname = {
style = "green";
format = "[$hostname]($style)";
ssh_only = false;
};
directory = {
style = "blue";
format = "[$path]($style)";
truncation_length = 3;
};
character = {
success_symbol = " >";
error_symbol = " >";
};
};
};
}

View file

@ -0,0 +1,37 @@
mailserver:
oauth:
client-id: ENC[AES256_GCM,data:oO2l88K/Tv0EMXQ/8KHpmWspYSKUENboPrWJHhbsrgR9HU9B1xXbnw==,iv:hhXZjZwAcx2KDaiMekv3lO6oFO6p/q4PpiN5R0jUBFs=,tag:fm3ykAcO2jU0JkSFZiQ15Q==,type:str]
client-secret: ENC[AES256_GCM,data:b+yUxUCqa8hXbUxMY2GqNMsEf0nG1Mpx36s98WIgSZEWVoLNvjQmPQDJpjP9/ESWqHP4ygc2KLFU+JpG+P0pNw==,iv:7gfq/sK2TtPXIC2ghYt7bYqg6gcXTtU4OAACITbbt5g=,tag:NB3EtaUEqK0VjVsEFLC/uQ==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSVXNQTzcydW1aaUhPWVNU
ME45VlF2a0tMOXM1Y05NQkphS3Mxd1BzNjJBCkoyT21XNnNyN3l2N3dUendabVRX
UU1BNWNYaEJuc0xhM2dCUDBrOFc2UnMKLS0tIGJlUUcxa0lLdGpDc3oyOC9Yc2hu
US83Q3hCNFRPeWtRckEza2l6eTk3Mm8K4U+9Xv+ygFAaV2avf8AoK9+P5w1Ni8PR
+msTgvLI3x8pXA2nYXq6s/yRwXwtbe+cLg0js7zWf6QCFdKFzqoQNw==
-----END AGE ENCRYPTED FILE-----
recipient: age1mgels4hjl7l07gcnt72g86kvhrvd82fha9kuvlp46mpks7unrpmqvy959u
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKQ1krS3A2b1IwZ3RPemhn
R0tiYVpJOEVHeGI3ZitxMVpBWHFNUlNrMkNFCnUzTHBDUGVPTXh3WGhrdmJJSDl3
T0RPalZFTGlpRkhPOW5tcmJuZHNQdlEKLS0tIE9lY0pIRWIwYkJHd1JocWpUY2c3
elkvcUJsT1UwRHV4SDRMS2w0R3Y0WjgKb0vtH0Ta2WyhBuusOYds25ikZ4FEG415
EbSGxQQo84gBg5nfY0W+JnOttJpGUAnxf5kQYYR3rVSxwPc0J7YJJg==
-----END AGE ENCRYPTED FILE-----
recipient: age1dcvh6q9953es9fvt8rq8rdgcktlt64asn2tf2y3vmyz0gntxzynqg2xgzk
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCNHFKcTRzV2hSa1Eybnk2
cjRZdXRwSFBLLzRRRnpGcFp5Z042UUlVL3djCjhJTWJMbklxTWhzOWQ2NmxyMUJm
T0QxUTZTNzRGUnlaY3FhWlk2bkhSb2MKLS0tIDd4MWhhK2JNeGFQTE1zSVE2Zmt3
TVp2NlJqMWtzY3JJSU5ITlNoR3VSalUKFxw0yQLsHNeR28Nfa8w9SMW7gT94vAZ0
y4hREV9XkRpoqoAFcc32TLcp9jdZE0Mh74tuyXDEtbHubWT7z9umhA==
-----END AGE ENCRYPTED FILE-----
recipient: age1hlsu7fdwwfm93rjt686j9cdy5klefwdus9jdxt5e0vaqh8c2la9qu5utns
lastmodified: "2026-05-24T20:07:18Z"
mac: ENC[AES256_GCM,data:7V/0fPY/c0nS3DjvDoBTq7wcvAZ/aFUMM/A6bo90U90tmtVIn9Iu8aeYdxbQeHJLzlAKb1oiRNmcKPmlrAI7AT9eaLX52JYZhYcDsLrHzoWo2tRBP4ZEvgvs2bZfqPfzvrdk4mCJ21WWYGLO4lm8i5V4ZDYMb3ezA/h132cpFfs=,iv:0sdfZ5W8KHp92u3HfCZUZexFoomugzbhatatcsdrucs=,tag:nV3OjlNl/ufROREDuE4WVw==,type:str]
unencrypted_suffix: _unencrypted
version: 3.13.1

View file

@ -0,0 +1,48 @@
{ pkgs, ... }:
{
services.caddy = {
enable = true;
# globalConfig = ''
# servers {
# trusted_proxies static cloudflare
# }
# '';
virtualHosts."http://kazusa.icn.mizuki.guru".extraConfig = ''
respond "" 200
'';
virtualHosts."designmerge.co.kr".extraConfig = ''
reverse_proxy 127.0.0.1:1108
'';
virtualHosts."plutos.dazzle.st".extraConfig = ''
reverse_proxy epc.hikari.mizuki.arpa:3000
'';
virtualHosts."kurumi.dazzle.st".extraConfig = ''
respond 204
'';
virtualHosts."pluto.dazzle.st".extraConfig = ''
respond 204
'';
virtualHosts."note.dazzle.st".extraConfig = ''
respond 204
'';
virtualHosts."report.dazzle.st".extraConfig = ''
respond 204
'';
package = pkgs.caddy.withPlugins {
plugins = [
"github.com/caddy-dns/cloudflare@v0.2.2"
"github.com/aksdb/caddy-cgi/v2@v2.2.6"
"github.com/shift72/caddy-geo-ip@v0.6.0"
"github.com/lolPants/caddy-requestid@v1.1.2"
"github.com/WeidiDeng/caddy-cloudflare-ip@v0.0.0-20231130002422-f53b62aa13cb"
"github.com/caddyserver/ntlm-transport@v0.1.2"
"github.com/ueffel/caddy-brotli@v1.6.0"
"github.com/RussellLuo/caddy-ext/ratelimit@v0.3.0"
"github.com/neodyme-labs/user_agent_parse@v0.0.1"
];
hash = "sha256-n0LkDBE3JB3zrGYND0EGrKXC+CT0SzRiIjj0QXNZZ8k=";
};
};
}

View file

@ -0,0 +1,201 @@
{
config,
pkgs,
lib,
...
}:
let
mailSecret = key: {
sopsFile = ../secrets/mailserver.yaml;
inherit key;
owner = "nginx";
group = "nginx";
mode = "0440";
restartUnits = [
"phpfpm-roundcube.service"
"dovecot.service"
];
};
clientIdSecret = config.sops.secrets."mailserver/oauth/client-id".path;
clientSecret = config.sops.secrets."mailserver/oauth/client-secret".path;
in
{
sops.secrets."mailserver/oauth/client-id" = mailSecret "mailserver/oauth/client-id";
sops.secrets."mailserver/oauth/client-secret" = mailSecret "mailserver/oauth/client-secret";
imports = [
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/51726d7b7fd94aa69829fd42749a803914cbf3b7/nixos-mailserver-51726d7b7fd94aa69829fd42749a803914cbf3b7.tar.gz";
sha256 = "0449ssnpwbgfv0cyddzb8s6g641gy5xh1hd3shg32x8pv0a5qy3a";
})
];
security.acme.acceptTerms = false;
services.roundcube = {
enable = true;
hostName = "mail.mizuki.guru";
package = pkgs.roundcube.withPlugins (
plugins: with plugins; [
persistent_login
]
);
plugins = [
"persistent_login"
"managesieve"
];
dicts = with pkgs.aspellDicts; [
en
];
maxAttachmentSize = config.mailserver.messageSizeLimit / 1024 / 1024;
extraConfig = ''
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = 443;
$_SERVER['HTTP_X_FORWARDED_PORT'] = 443;
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
$_SERVER['HTTP_HOST'] = 'mail.mizuki.guru';
$config['proxy_ips'] = '127.0.0.1';
$config['imap_host'] = "ssl://${config.mailserver.fqdn}";
$config['smtp_host'] = "ssl://${config.mailserver.fqdn}";
$config['smtp_user'] = "%u";
$config['smtp_pass'] = "%p";
$config['managesieve_host'] = "tls://${config.mailserver.fqdn}";
$config['managesieve_port'] = 4190;
$config['managesieve_usetls'] = true;
$config['oauth_provider'] = 'generic';
$config['oauth_provider_name'] = 'authentik';
$config['oauth_client_id'] =
trim(file_get_contents('${clientIdSecret}'));
$config['oauth_client_secret'] =
trim(file_get_contents('${clientSecret}'));
$config['oauth_auth_uri'] =
'https://auth.mizuki.guru/application/o/authorize/';
$config['oauth_token_uri'] =
'https://auth.mizuki.guru/application/o/token/';
$config['oauth_identity_uri'] =
'https://auth.mizuki.guru/application/o/userinfo/';
$config['oauth_scope'] =
"email openid dovecotprofile offline_access";
$config['oauth_auth_parameters'] = [];
$config['oauth_identity_fields'] = ['email'];
'';
};
services.nginx.virtualHosts.${config.services.roundcube.hostName} = {
forceSSL = false;
enableACME = false;
listen = [
{
addr = "127.0.0.1";
port = 5656;
}
];
extraConfig = ''
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
'';
};
services.caddy = {
enable = true;
virtualHosts."mail.mizuki.guru" = {
extraConfig = ''
reverse_proxy localhost:5656
'';
};
};
services.dovecot2.settings = {
auth_mechanisms = lib.mkForce [
"plain"
"login"
"xoauth2"
"oauthbearer"
];
oauth2_tokeninfo_url = "https://auth.mizuki.guru/application/o/userinfo/?access_token=";
# 주의:
# 여기는 아직 secret '값'이 아니라 secret '경로'가 들어감.
# Dovecot이 URL 안에서 file_get_contents 같은 처리를 안 하므로
# 이 방식은 제대로 동작하지 않을 가능성이 큼.
oauth2_introspection_url = "https://auth.mizuki.guru/application/o/introspect/";
oauth2_introspection_mode = "post";
oauth2_force_introspection = "yes";
oauth2_active_attribute = "active";
oauth2_active_value = "true";
oauth2_username_attribute = "email";
};
users.users.dovecot = {
isSystemUser = true;
group = "dovecot";
extraGroups = [ "caddy" ];
};
users.groups.dovecot = { };
users.users.postfix.extraGroups = [ "caddy" ];
mailserver = {
enable = true;
stateVersion = 4;
fqdn = "mail.mizuki.guru";
domains = [ "mizuki.guru" ];
x509 = {
certificateFile = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.mizuki.guru/mail.mizuki.guru.crt";
privateKeyFile = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mail.mizuki.guru/mail.mizuki.guru.key";
};
ldap = {
enable = true;
uris = [ "ldap://10.11.8.102" ];
bind = {
dn = "cn=mailserver,ou=users,dc=ldap,dc=goauthentik,dc=io";
passwordFile = "/var/lib/secrets/authentik-ldap-bind-pw";
};
base = "ou=users,dc=ldap,dc=goauthentik,dc=io";
scope = "sub";
attributes = {
uuid = "uid";
username = "mail";
mail = "mail";
};
dovecot = {
passFilter = "mail=%{user}\n bind = yes";
};
};
accounts = { };
};
}