Compare commits

..

4 Commits

Author SHA1 Message Date
Alexander Tomokhov 45faf8e15b configuration diagrams 2023-08-23 02:45:38 +04:00
Alexander Tomokhov 5fc4648b46 nixos-config: delete schema files 2023-07-15 15:53:37 +04:00
Alexander Tomokhov cbfbee3123 nixos-config: python app writes userdata.json 2023-07-15 15:37:24 +04:00
Alexander Tomokhov d5a4b255df NixOS configuration restructuring diagram 1 2023-07-15 04:55:50 +04:00
8 changed files with 703 additions and 123 deletions

View File

@ -0,0 +1,188 @@
@startuml
/'
' left to right direction
'/
/'
' skin rose
'/
cloud "overlay\n<i>commit @ git.selfprivacy.org" as overlay {
node "selfprivacy graphql api" as selfprivacy_graphql_api
}
cloud "selfprivacy-rest-api\n<i>commit @ git.selfprivacy.org" as selfprivacy_rest_api_commit {
component "python app" as selfprivacy_api_app
}
control "client app" as client_app
:user: .. client_app
selfprivacy_api_app . client_app
selfprivacy_graphql_api <<-- selfprivacy_rest_api_commit
file "hardware-configuration.nix" as hardware_configuration
card "grub.device" as hw_grub_device
card "initrd.kernelModules" as hw_kernelModules
card "fileSystems" as hw_fileSystems
hardware_configuration <-- hw_grub_device
hardware_configuration <-- hw_kernelModules
hardware_configuration <-- hw_fileSystems
note top of hardware_configuration : how is it generated?
note bottom of hw_fileSystems : always the same?
note "hosting dependant" as note_hosting
hw_grub_device <<.. note_hosting
hw_kernelModules <<.. note_hosting
file "api.nix\napi-module.nix" as api
file files [
files.nix
---
""systemd.tmpfiles.rules""
""systemd.activationScripts""
""/var/lib/nextcloud""
""/var/lib/cloudflare""
""/var/lib/pleroma""
""/var/lib/bitwarden""
""/root/.config/rclone""
]
file "volumes.nix" as volumes {
card "fileSystems" as fileSystems_from_userdata
}
file "users.nix" as users {
card "users.users" as users_from_userdata
}
file "variables.nix\nvariables-module.nix" as variables
file "letsencrypt/acme.nix\nletsencrypt/resolve.nix" as acme
/'
' file "backup/restic.nix" as restic
' file "gitea.nix" as gitea
' file "mailserver/system/mailserver.nix" as mailserver
' file "nextcloud.nix" as nextcloud
' file "passmgr/bitwarden.nix" as bitwarden
' file "limits.nix" as limits
' file "pleroma.nix" as pleroma
' file "jitsi.nix" as jitsi
' file "vpn/ocserv.nix" as ocserv
' file "webserver/nginx.nix" as nginx
' file "webserver/memcached.nix" as memcached
'/
collections "<<some service X.nix>>" as some_service
cloud " <b>nixpkgs\n<i>commit @ github.com (?)" as nixpkgs
folder """/etc/nixos/userdata/""" as userdata_folder {
/'
' file "schema.json\n<i>(who uses?)" as schema
' file "tokens_schema.json\n<i>(who uses?)" as tokens_schema
'/
file "tokens.json" as tokens
file "<b>userdata.json" as userdata
}
selfprivacy_api_app <|.... tokens
selfprivacy_api_app ....|> userdata_folder : writes
file "<b><u>configuration.nix" as configuration
nixpkgs -->> configuration
configuration <<-l- hardware_configuration
/'
' configuration <<-- overlay
'/
overlay -->> configuration
configuration <<-- variables : ...\nstateVersion\n...
configuration <<-- files
userdata -[dotted]->> files
files <|-- userdata : <b>secrets\nby ""jq"" and ""sed"" in\n""activationScripts""\n!!!
variables <<-- userdata : values extraction\nfrom JSON
configuration <<-- volumes
userdata -[dotted]->> fileSystems_from_userdata : volumes
configuration <<-- users
userdata -[dotted]->> users_from_userdata : users
configuration <<-- api
api <<-[dotted]- userdata : Swagger,\nb2Bucket
api <-[dotted]- selfprivacy_graphql_api
configuration <<-- acme
userdata -[dotted]->> acme : username,\ndomain
configuration <<-- some_service
userdata -[dotted]->> some_service : enable,\nsettings
/'
' configuration <<-- mailserver
' userdata -[dotted]->> mailserver
'
' configuration <<-- ocserv
' userdata -[dotted]->> ocserv
' configuration <<-- pleroma
' userdata -[dotted]->> pleroma
'
' configuration <<-- restic
' userdata -[dotted]-->> restic
'
' configuration <<-- bitwarden
' userdata -[dotted]-->> bitwarden
'
' configuration <<-- nginx
' userdata -[dotted]->> nginx : domain
'
' configuration <<-- memcached
'
' configuration <<-- nextcloud
' userdata -[dotted]-->> nextcloud : enable,\ndomain
'
' configuration <<-- jitsi
' userdata -[dotted]-->> jitsi : enable,\ndomain
'
' configuration <<-- gitea
' userdata -[dotted]-->> gitea : enable,\ndomain
'/
/'
' memcached --->> configuration
'/
/'
' folder api as api_folder
' folder backup as backup_folder
' folder git as git_folder
' folder letsencrypt as letsencrypt_folder
' folder "mailserver/system" as mailserver_folder
' folder nextcloud as nextcloud_folder
' folder passmgr as passmgr_folder
' folder resources as resources_folder
' folder social as social_folder
' folder videomeet as videomeet_folder
' folder vpn as vpn_folder
' folder webserver as webserver_folder
'/
/'
' api_folder -- api_module
' api_folder -- api
' backup_folder -- restic
' git_folder -- gitea
' letsencrypt_folder -- acme
' letsencrypt_folder -- resolve
' mailserver_folder -- mailserver
' nextcloud_folder -- nextcloud
' passmgr_folder -- bitwarden
' resources_folder -- limits
' social_folder -- pleroma
' videomeet_folder -- jitsi
' vpn_folder -- ocserv
' webserver_folder -- memcached
' webserver_folder -- nginx
'/
@enduml

View File

@ -0,0 +1,204 @@
@startuml
/'
' left to right direction
'/
/'
' skin rose
'/
<style>
cloud {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
folder {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
</style>
cloud "overlay\n<i>commit @ git.selfprivacy.org" as overlay {
node "selfprivacy-graphql-api" as selfprivacy_graphql_api
}
cloud "selfprivacy-rest-api\n<i>commit @ git.selfprivacy.org" as selfprivacy_rest_api_commit {
component "python app" as selfprivacy_api_app
}
control "client app" as client_app
:user: .. client_app
selfprivacy_api_app . client_app
selfprivacy_graphql_api <<-- selfprivacy_rest_api_commit
file "hardware-configuration.nix" as hardware_configuration #lightcyan
card "grub.device" as hw_grub_device
card "initrd.kernelModules" as hw_kernelModules
card "fileSystems" as hw_fileSystems
hardware_configuration <-- hw_grub_device
hardware_configuration <-- hw_kernelModules
hardware_configuration <-- hw_fileSystems
note top of hardware_configuration : generated by\nnixos-infect
note bottom of hw_fileSystems : always the same?
note "hosting dependant" as note_hosting
hw_grub_device <<.. note_hosting
hw_kernelModules <<.. note_hosting
file "api.nix\napi-module.nix" as api
file files [
files.nix
---
""systemd.tmpfiles.rules""
""systemd.activationScripts""
""/var/lib/nextcloud""
""/var/lib/cloudflare""
""/var/lib/pleroma""
""/var/lib/bitwarden""
""/root/.config/rclone""
]
file "volumes.nix" as volumes {
card "fileSystems" as fileSystems_from_userdata
}
file "users.nix" as users {
card "users.users" as users_from_userdata
}
file "variables.nix\nvariables-module.nix" as variables
file "letsencrypt/acme.nix\nletsencrypt/resolve.nix" as acme
/'
' file "backup/restic.nix" as restic
' file "gitea.nix" as gitea
' file "mailserver/system/mailserver.nix" as mailserver
' file "nextcloud.nix" as nextcloud
' file "passmgr/bitwarden.nix" as bitwarden
' file "limits.nix" as limits
' file "pleroma.nix" as pleroma
' file "jitsi.nix" as jitsi
' file "vpn/ocserv.nix" as ocserv
' file "webserver/nginx.nix" as nginx
' file "webserver/memcached.nix" as memcached
'/
collections "<<some service X.nix>>" as some_service
cloud " <b>nixpkgs\n<i>commit @ github.com (?)" as nixpkgs
folder """/etc/nixos/userdata/""" as userdata_folder {
/'
' file "schema.json\n<i>(who uses?)" as schema
' file "tokens_schema.json\n<i>(who uses?)" as tokens_schema
'/
file "tokens.json" as tokens
file "<b>userdata.json" as userdata
}
/'
' note left of userdata : first generated by\nnixos-infect
'/
selfprivacy_api_app <|.... tokens
selfprivacy_api_app ....|> userdata_folder : writes
file "<b><u>configuration.nix" as configuration
nixpkgs -->> configuration
configuration <<-l- hardware_configuration
/'
' configuration <<-- overlay
'/
overlay -->> configuration
configuration <<-- variables : ...\nstateVersion\n...
configuration <<-- files
userdata -[dotted]->> files
files <|-- userdata : <b>secrets\nby ""jq"" and ""sed"" in\n""activationScripts""\n!!!
variables <<-- userdata : values extraction\nfrom JSON
configuration <<-- volumes
userdata -[dotted]->> fileSystems_from_userdata : volumes
configuration <<-- users
userdata -[dotted]->> users_from_userdata : users
configuration <<-- api
api <<-[dotted]- userdata : Swagger,\nb2Bucket
api <-[dotted]- selfprivacy_graphql_api
configuration <<-- acme
userdata -[dotted]->> acme : username,\ndomain
configuration <<-- some_service
userdata -[dotted]->> some_service : enable,\nsettings
/'
' configuration <<-- mailserver
' userdata -[dotted]->> mailserver
'
' configuration <<-- ocserv
' userdata -[dotted]->> ocserv
' configuration <<-- pleroma
' userdata -[dotted]->> pleroma
'
' configuration <<-- restic
' userdata -[dotted]-->> restic
'
' configuration <<-- bitwarden
' userdata -[dotted]-->> bitwarden
'
' configuration <<-- nginx
' userdata -[dotted]->> nginx : domain
'
' configuration <<-- memcached
'
' configuration <<-- nextcloud
' userdata -[dotted]-->> nextcloud : enable,\ndomain
'
' configuration <<-- jitsi
' userdata -[dotted]-->> jitsi : enable,\ndomain
'
' configuration <<-- gitea
' userdata -[dotted]-->> gitea : enable,\ndomain
'/
/'
' memcached --->> configuration
'/
/'
' folder api as api_folder
' folder backup as backup_folder
' folder git as git_folder
' folder letsencrypt as letsencrypt_folder
' folder "mailserver/system" as mailserver_folder
' folder nextcloud as nextcloud_folder
' folder passmgr as passmgr_folder
' folder resources as resources_folder
' folder social as social_folder
' folder videomeet as videomeet_folder
' folder vpn as vpn_folder
' folder webserver as webserver_folder
'/
/'
' api_folder -- api_module
' api_folder -- api
' backup_folder -- restic
' git_folder -- gitea
' letsencrypt_folder -- acme
' letsencrypt_folder -- resolve
' mailserver_folder -- mailserver
' nextcloud_folder -- nextcloud
' passmgr_folder -- bitwarden
' resources_folder -- limits
' social_folder -- pleroma
' videomeet_folder -- jitsi
' vpn_folder -- ocserv
' webserver_folder -- memcached
' webserver_folder -- nginx
'/
@enduml

View File

@ -0,0 +1,95 @@
@startuml
left to right direction
<style>
cloud {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
folder {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
</style>
node "NixOS machine" as machine {
file "hardware-configuration.nix" as hardware_configuration #lightcyan
folder """userdata/""" as userdata_folder {
/'
' file "schema.json\n<i>(who uses?)" as schema
' file "tokens_schema.json\n<i>(who uses?)" as tokens_schema
'/
file "tokens.json" as tokens
file "<b>userdata.json" as userdata
}
collections "/nix/store/*" as nix_store
/'
' file local_flake [
' <b>flake.nix
' ===
' inputs = {
' selfprivacy-nixos-config.url = ...;
' };
' outputs = {
' nixosConfigurations =
' selfprivacy-nixos-config.outputs.nixosConfigurations-fun userdata;
' };
' ]
'/
}
folder "configuration repo" as config_repo {
/'
' file "flake.nix" as flake_nix {
' card "input: nixpkgs.url"
' card "input: selfprivacy-overlay.url"
' }
'/
file flake_nix [
<b>flake.nix
===
inputs = {
nixpkgs.url = ...;
selfprivacy-overlay.url = ...;
};
]
file flake_lock [
<b>flake.lock
]
flake_lock - flake_nix
note top of flake_lock : pinning with hashes
file "<b><u>configuration.nix" as configuration
collections "pure imports" as pure_imports
}
cloud "overlay\n<i>commit @ git.selfprivacy.org" as overlay {
node "selfprivacy-graphql-api" as selfprivacy_graphql_api
}
cloud "selfprivacy-rest-api\n<i>commit @ git.selfprivacy.org" as selfprivacy_rest_api_commit {
component "python app" as selfprivacy_api_app
}
cloud " <b>nixpkgs\n<i>commit @ github.com (?)" as nixpkgs
nixpkgs --> flake_lock
overlay --> flake_lock
configuration <-- userdata : <b>impure!
configuration <-- hardware_configuration : <b>impure!
selfprivacy_rest_api_commit -->> selfprivacy_graphql_api
flake_nix --> configuration
flake_lock --> configuration
configuration -[bold]-|> nix_store : nixos-rebuild
configuration <-l- pure_imports
@enduml

View File

@ -0,0 +1,102 @@
@startuml
left to right direction
<style>
cloud {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
folder {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
control {
BackGroundColor lightpink
}
</style>
folder "configuration repo" as config_repo {
/'
' file "flake.nix" as flake_nix {
' card "input: nixpkgs.url"
' card "input: selfprivacy-overlay.url"
' }
'/
file flake_nix [
<b>flake.nix
===
inputs = {
nixpkgs.url = ...;
selfprivacy-overlay.url = ...;
userdata-json.flake = false;
hardware-configuration-nix.flake = false;
};
outputs = { ... }: {
nixosConfigurations = ... {
specialArgs = { ... userdata; };
modules = [
{ nixpkgs.overlays = [ selfprivacy-overlay ]; }
hardware-configuration
./configuration.nix
];
};
};
]
file flake_lock [
<b>flake.lock
]
flake_lock - flake_nix
note top of flake_lock : pinning with hashes
file "<b><u>configuration.nix" as configuration
collections "nix modules" as pure_imports
}
node "NixOS machine" as machine {
file "hardware-configuration.nix" as hardware_configuration #lightcyan
folder """userdata/""" as userdata_folder {
/'
' file "schema.json\n<i>(who uses?)" as schema
' file "tokens_schema.json\n<i>(who uses?)" as tokens_schema
'/
file "tokens.json" as tokens
file "<b>userdata.json" as userdata
tokens -l[hidden]- userdata
}
collections "/nix/store/*" as nix_store
control "<font:monospaced><size:15>nixos-rebuild" as nixos_rebuild
}
cloud "overlay\n<i>commit @ git.selfprivacy.org" as overlay {
node "selfprivacy-graphql-api" as selfprivacy_graphql_api
}
cloud "selfprivacy-rest-api\n<i>commit @ git.selfprivacy.org" as selfprivacy_rest_api_commit {
component "python app" as selfprivacy_api_app
}
cloud " <b>nixpkgs\n<i>commit @ github.com (?)" as nixpkgs
nixpkgs --> flake_lock
overlay --> flake_lock
nixos_rebuild <- userdata : <font:monospaced>--override-input
nixos_rebuild <-l- hardware_configuration : <font:monospaced>--override-input
selfprivacy_rest_api_commit ->> selfprivacy_graphql_api
flake_nix --> configuration
flake_lock --> configuration
configuration -d-> nixos_rebuild
nixos_rebuild -[bold]-|> nix_store
configuration <-l- pure_imports
footer %date("yyyy-MM-dd'T'HH:mmZ")
@enduml

View File

@ -0,0 +1,107 @@
@startuml
left to right direction
<style>
cloud {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
folder {
LineThickness 3
LineColor lightblue
BackGroundColor lightcyan
}
</style>
node "NixOS machine" as machine {
file "hardware-configuration.nix" as hardware_configuration #lightcyan
folder """userdata/""" as userdata_folder {
/'
' file "schema.json\n<i>(who uses?)" as schema
' file "tokens_schema.json\n<i>(who uses?)" as tokens_schema
'/
file "tokens.json" as tokens
file "<b>userdata.json" as userdata
tokens -l[hidden]- userdata
}
collections "/nix/store/*" as nix_store
file local_flake_nix [
<b>flake.nix
===
inputs = {
selfprivacy-nixos-config.url = ...;
};
outputs = {
nixosConfigurations =
selfprivacy-nixos-config.outputs.nixosConfigurations-fun
hardware-configuration userdata;
};
]
/'
' file local_flake_lock as "flake.lock"
' local_flake_nix -l- local_flake_lock
'/
}
folder "configuration repo" as config_repo {
/'
' file "flake.nix" as flake_nix {
' card "input: nixpkgs.url"
' card "input: selfprivacy-overlay.url"
' }
'/
file flake_nix [
<b>flake.nix
===
inputs = {
nixpkgs.url = ...;
selfprivacy-overlay.url = ...;
};
outputs = {
nixosConfigurations-fun =
hardware-configuration: userdata:
...;
};
]
file flake_lock [
<b>flake.lock
]
flake_lock - flake_nix
note top of flake_lock : pinning with hashes
file "<b><u>configuration.nix" as configuration
collections "pure imports" as pure_imports
}
cloud "overlay\n<i>commit @ git.selfprivacy.org" as overlay {
node "selfprivacy-graphql-api" as selfprivacy_graphql_api
}
cloud "selfprivacy-rest-api\n<i>commit @ git.selfprivacy.org" as selfprivacy_rest_api_commit {
component "python app" as selfprivacy_api_app
}
cloud " <b>nixpkgs\n<i>commit @ github.com (?)" as nixpkgs
nixpkgs --> flake_lock
overlay --> flake_lock
local_flake_nix <-r- userdata
local_flake_nix <-l- hardware_configuration
selfprivacy_rest_api_commit -->> selfprivacy_graphql_api
flake_nix --> configuration
flake_lock --> configuration
configuration --> local_flake_nix
local_flake_nix -[bold]-|> nix_store : nixos-rebuild
configuration <-l- pure_imports
footer %date("yyyy-MM-dd'T'HH:mmZ")
@enduml

View File

@ -1,28 +0,0 @@
@startuml
state "current state" as current
current : NixOS 22.11 w/o flakes
state "next state" as next
next : NixOS 22.11 w/ flakes
state "future state" as future
future : NixOS 23.05 w/ flakes
state "initial state" as initial
initial : "Ubuntu"
initial -r-> next : implemented &\ntested @ hetzner\nTODO: digital-ocean
current --> next : not tested\n(2023-11-30)
next --> future
note right of next
updated
application
needed
end note
next -u[#red,dashed]-> current : full rollback\n<color:red><b>not possible\n(hard to implement)
future --> next : full rollback\npossible
@enduml

View File

@ -1,76 +0,0 @@
@startuml
title SP NixOS state diagram
hide empty description
state "Ubuntu state" as ubuntu_state
state "SP NixOS" as sp_nixos {
state "clean state" as clean_state
clean_state : * /etc/nixos = /etc/selfprivacy/nixos-config-source
clean_state : * system @ profile<sub>N</sub>
clean_state : * bootloader @ profile<sub>N</sub>
clean_state : * all services up
state "modified config state" as modified_state
modified_state : * /etc/nixos ≠ /etc/selfprivacy/nixos-config-source
modified_state : * system @ profile<sub>N</sub>
modified_state : * bootloader @ profile<sub>N</sub>
modified_state : * all services up
state "new profile <color:red>failed activation</color> state" as new_profile_failed_activation_state
new_profile_failed_activation_state : * /etc/nixos = /etc/selfprivacy/nixos-config-source
new_profile_failed_activation_state : * system @ profile<sub>N+1</sub>
new_profile_failed_activation_state : * bootloader @ profile<sub>N+1</sub>
new_profile_failed_activation_state : * some <color:red>services failed
state "old profile <color:red>without activation</color> state" as old_profile_no_activation_state
old_profile_no_activation_state : * /etc/nixos = /etc/selfprivacy/nixos-config-source
old_profile_no_activation_state : * system @ profile<sub>N-1</sub>
old_profile_no_activation_state : * <color:red>bootloader @ profile<sub>N</sub>
old_profile_no_activation_state : * <color:red>no services reload
/'
' state "new profile <color:red>failed bootloader state" as new_profile_failed_bootloader_state
' new_profile_failed_bootloader_state : * /etc/nixos = /etc/selfprivacy/nixos-config-source
' new_profile_failed_bootloader_state : * system @ profile<sub>N+1</sub>
' new_profile_failed_bootloader_state : * <color:red>bootloader @ profile<sub>N</sub>
' new_profile_failed_bootloader_state : * all services up
'/
[*] --> clean_state : boot
clean_state --> modified_state : <u>modify by API:\n""userdata.json""\n""sp-modules/flake.nix""\n<u>NixOS & SP modules update:\n""flake.lock""\n
modified_state -u-> modified_state : \n\n\n\n\n\n\nnixos-rebuild switch\n<color:red>build\n<color:red>failure
modified_state -u-> modified_state : nixos-rebuild switch\n<color:red>bootloader\n<color:red>update\n<color:red>failure
modified_state -l-> new_profile_failed_activation_state : nixos-rebuild switch\n<color:red>activation\n<color:red>failure
clean_state -u-> clean_state : \nrollback\nto profile<sub>N-1</sub>
clean_state -l-> old_profile_no_activation_state : rollback\n<color:red>bootloader\n<color:red>update\n<color:red>failure
old_profile_no_activation_state -l-> [*] : <color:red>99% chance disk is full!\n<color:red>do something?\nreboot?
new_profile_failed_activation_state -u-> clean_state : rollback\nto profile<sub>N-1</sub>
state "new state" as new_state
new_state : * /etc/nixos = /etc/selfprivacy/nixos-config-source
new_state : * system @ profile<sub>N+1</sub>
new_state : * bootloader @ profile<sub>N+1</sub>
new_state : * <b><color:darkred>all services up?
modified_state --> new_state : nixos-rebuild switch\n@ profile<sub>N+1</sub>
new_state -u-> clean_state : <b><u>selftest\n<b><color:green>OK</color></b> => do nothing\n<b><color:red>FAIL</color></b> => <b>rollback
/'
' new_state --u-> clean_state : <b>selftest\n<b><color:red>FAIL => rollback
'/
}
[*] -r-> ubuntu_state : boot
ubuntu_state --> sp_nixos
note on link
nixos-infect
---
<- ""https://releases.nixos.org/nix/nix-${NIX_VERSION}/install""
<- ""https://git.selfprivacy.org/selfprivacy/selfprivacy-nixos-infect""
end note
' <- ""https://git.selfprivacy.org/selfprivacy/selfprivacy-nixos-config""
footer %date("yyyy-MM-dd'T'HH:mmZ")
@enduml

View File

@ -8,15 +8,11 @@ Generally, it's better to implement as many layers of security as possible. Alth
Systemd is the standard software suite for organizing and running services/daemons in a modern GNU/Linux distribution, including NixOS. Systemd provides means to secure services. And in many ways, the isolation level of a systemd service can be similar to that of containers (by the means of sandboxing, namespaces and cgroups, which Docker also uses; interestingly, [systemd even allows running](https://www.stevenrombauts.be/2019/01/run-multiple-instances-of-the-same-systemd-unit/) [multiple instances of the same service](https://opensource.com/article/20/12/multiple-service-instances-systemctl)). However, systemd hardening defaults are quite loose (perhaps, not to disturb the operation of newly written services and their administrators in any way).
What NixOS does - it generates systemd configuration files in accordance to NixOS configuration given, written in the Nix language. To some extent, Nix acts as an advanced macro language. Whereas, NixOS configuration module system acts as a unified control center, so that you don't bother about location of systemd files, their syntax and common stuff, which NixOS generates for you. Also, NixOS manages switching between systemd configurations (when you call for it), conducting services restarts when required, and whole system rollbacks from GRUB/systemd-boot/extlinux.
---
_NixOS rollbacks are cheap. Based on the Nix storage model, they do not take additional disk space (except metadata). So, there is virtually no need for system backups/snapshots._
What NixOS does - it generates systemd configuration files in accordance to NixOS configuration given, written in Nix language. To some extent, Nix acts as a macro language and NixOS configuration module system acts as a unified control center, so that you don't bother about location of systemd files, their syntax and common stuff, which NixOS generates for you. Also, NixOS manages runtime switching between systemd configurations, conducting services restarts when required, and whole system rollbacks from GRUB/systemd-boot/extlinux.
## overview of systemd services integration within NixOS configuration
NixOS features lots of systemd services, which are ready to use (without even knowing what systemd is) just by setting appropriate options in `configuration.nix`. For example, write `services.netdata.enable = true;` to enable [Netdata](https://www.netdata.cloud/) monitoring service. Often many useful high-level tunables are available as `services.<name>.*` options.
NixOS features lots of systemd services, which are ready to use (without even knowing what systemd is) just by setting appropriate options in `configuration.nix`. For example, write `services.netdata.enable = true;` to enable [Netdata](https://www.netdata.cloud/) monitoring service. Documentation for all related options can be found on the [website](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.) or in `man configuration.nix` _(also in `man home-configuration.nix` for [managing desktop](https://github.com/nix-community/home-manager) user services)_. Often many useful high-level tunables are available as `services.<name>.*` options.
When services, provided by NixOS, are insufficient or additional tuning is demanded, `systemd.services.<name>.*` set of options comes into play. They allow to define custom systemd services or modify existing ones. Regardless of the origin of a systemd service (provided by NixOS or written by yourself), `systemd` native directives for sections such as `[Unit]` and `[Service]` can be specified accordingly in the following [nix attribute sets](https://nixos.org/manual/nix/stable/language/values.html#attribute-set):
@ -36,29 +32,22 @@ You can find more information about such options [online](https://search.nixos.o
In a nutshell, configuring systemd options for services on NixOS typically boils down to these steps:
1. edit `systemd.services.*` options in `configuration.nix` or in other imported nix files;
2. run `sudo nixos-rebuild test` to apply new configuration just for the current OS boot or `sudo nixos-rebuild switch` to apply changes permanently (additionally add `--flake /etc/nixos` for flakes);
2. run `sudo nixos-rebuild test` to apply new configuration just for now or `sudo nixos-rebuild switch` to apply changes permanently;
3. evaluate `systemd` service operation (we will elaborate on this further);
4. return to step 1 or finish.
Alternatively, new configurations can be tested inside a QEMU VM clone of your system without affecting your running system configuration. `nixos-build build-vm` leaves a symlink `./result` in the current directory that contains the built VM. To run it, use `result/bin/run-<hostname>-vm`.
Be aware that systemd directives (options) are case sensitive! But NixOS doesn't know whether systemd recognizes any directives or not, whereas systemd does not complain neither! So, once new configuration is applied, analyze the output of these commands and compare with the intended objectives:
Be aware that systemd directives (options) are case sensitive! But NixOS doesn't know whether systemd recognizes any directives or not, whereas systemd does not complain neither! So, once new configuration is applied, analyze output of these commands and compare with intended objectives:
* `systemctl cat <name>` - contents of a systemd unit file, generated by NixOS
* `systemctl show <name>` - actual properties of a systemd unit in effect
Also, keep in mind that mutable operations like `systemd <service> enable` are useless, because they would deviate the system from declarative reproducible configuration and NixOS won't let or will stubbornly resist you doing so at the design level. And there is no need, since each permanent setting is in the hands of NixOS.
Also, keep in mind that mutable operations like `systemd SERVICE enable` are useless, because they would deviate the system from declarative reproducible configuration and NixOS won't let or will stubbornly resist you doing so at the design level. And there is no need, since each permanent setting is in the hands of NixOS.
---
Documentation for all related options can be found on the [website](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.) or in `man configuration.nix` _(also in `man home-configuration.nix` for [managing desktop](https://github.com/nix-community/home-manager) user services)_.
---
Documentation for all related options can be found on the [website](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.) or in `man configuration.nix` _(also in `man home-configuration.nix` for [managing desktop](https://github.com/nix-community/home-manager) user services)_.
## tips for hardening
There is [no universal way](https://github.com/NixOS/nixpkgs/pull/87661#issuecomment-698945283) in configuring systemd services sandboxing/hardening options for all services. Each service requires an individual approach.
There is [no universal way](https://github.com/NixOS/nixpkgs/pull/87661#issuecomment-698945283) in configuring systemd services options sandboxing/hardening for all services. Each service requires individual approach.
NixOS provides many services, available as `services.<name>.*`, which already have more or less hardening implemented by the means of systemd. For example, `services.nginx`, `services.gitea`, `services.jitsi-meet`, `services.redis`. At least, these services run under specific system non-`root` users without access to spawn a shell.
@ -266,13 +255,12 @@ As of 2023-07-10 [`systemd.services.<name>.confinement.enable` NixOS option](htt
## final notes
Systemd hardening is just a part of measures to be taken to narrow the potential threat landscape and risks for a server. Ideally, vulnerabilities scanning, penetration testing, unauthorized access prevention and security audits should be involved. Take advantage of monitoring tools and react quickly, according to a rescue plan to mitigate the impact of intrusion incidents. This might include restoring system from backups, keys and passwords reset, etc. Keep running software up to date and respond to CVEs ([deploying software with patches is easy in NixOS](https://nixos.wiki/wiki/Overlays#Adding_patches) in case it hasn't been already patched). Have a business continuity plan. Many measures must not be ad-hoc, but rather systematic to stay vigilant against emerging threats.
Systemd hardening is just a part of measures to be taken to narrow the potential threat landscape and risks for a server. Ideally, vulnerabilities scanning, penetration testing, unauthorized access prevention and security audits should be involved. Take advantage of monitoring tools and respond quickly, according to a rescue plan to mitigate the impact of intrusion incidents. This might include restoring system from backups, keys and passwords reset, etc. Keep running software up to date and respond to CVEs ([deploying software with patches is easy in NixOS](https://nixos.wiki/wiki/Overlays#Adding_patches) in case it hasn't been already patched). Have a business continuity plan. Many measures must not be ad-hoc, but rather systematic to stay vigilant against emerging threats.
As for NixOS, it also features `security.apparmor`, `security.audit` and even `programs.firejail` options which might help in building a more secure system.
## related resources
- [add hardening to systemd services in NixOS tree](https://git.selfprivacy.org/alexoundos/articles)
- [discourse thread about systemd services hardening](https://discourse.nixos.org/t/hardening-systemd-services/17147)
- [systemd.resource-control man page](https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html)
- [systemd.exec - execution environment configuration](https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html)