at 25.11-pre 7.3 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7 8let 9 cfg = config.services.suwayomi-server; 10 inherit (lib) 11 mkOption 12 mkEnableOption 13 mkIf 14 types 15 ; 16 17 format = pkgs.formats.hocon { }; 18in 19{ 20 options = { 21 services.suwayomi-server = { 22 enable = mkEnableOption "Suwayomi, a free and open source manga reader server that runs extensions built for Tachiyomi"; 23 24 package = lib.mkPackageOption pkgs "suwayomi-server" { }; 25 26 dataDir = mkOption { 27 type = types.path; 28 default = "/var/lib/suwayomi-server"; 29 example = "/var/data/mangas"; 30 description = '' 31 The path to the data directory in which Suwayomi-Server will download scans. 32 ''; 33 }; 34 35 user = mkOption { 36 type = types.str; 37 default = "suwayomi"; 38 example = "root"; 39 description = '' 40 User account under which Suwayomi-Server runs. 41 ''; 42 }; 43 44 group = mkOption { 45 type = types.str; 46 default = "suwayomi"; 47 example = "medias"; 48 description = '' 49 Group under which Suwayomi-Server runs. 50 ''; 51 }; 52 53 openFirewall = mkOption { 54 type = types.bool; 55 default = false; 56 description = '' 57 Whether to open the firewall for the port in {option}`services.suwayomi-server.settings.server.port`. 58 ''; 59 }; 60 61 settings = mkOption { 62 type = types.submodule { 63 freeformType = format.type; 64 options = { 65 server = { 66 ip = mkOption { 67 type = types.str; 68 default = "0.0.0.0"; 69 example = "127.0.0.1"; 70 description = '' 71 The ip that Suwayomi will bind to. 72 ''; 73 }; 74 75 port = mkOption { 76 type = types.port; 77 default = 8080; 78 example = 4567; 79 description = '' 80 The port that Suwayomi will listen to. 81 ''; 82 }; 83 84 basicAuthEnabled = mkEnableOption '' 85 basic access authentication for Suwayomi-Server. 86 Enabling this option is useful when hosting on a public network/the Internet 87 ''; 88 89 basicAuthUsername = mkOption { 90 type = types.nullOr types.str; 91 default = null; 92 description = '' 93 The username value that you have to provide when authenticating. 94 ''; 95 }; 96 97 # NOTE: this is not a real upstream option 98 basicAuthPasswordFile = mkOption { 99 type = types.nullOr types.path; 100 default = null; 101 example = "/var/secrets/suwayomi-server-password"; 102 description = '' 103 The password file containing the value that you have to provide when authenticating. 104 ''; 105 }; 106 107 downloadAsCbz = mkOption { 108 type = types.bool; 109 default = false; 110 description = '' 111 Download chapters as `.cbz` files. 112 ''; 113 }; 114 115 extensionRepos = mkOption { 116 type = types.listOf types.str; 117 default = [ ]; 118 example = [ 119 "https://raw.githubusercontent.com/MY_ACCOUNT/MY_REPO/repo/index.min.json" 120 ]; 121 description = '' 122 URL of repositories from which the extensions can be installed. 123 ''; 124 }; 125 126 localSourcePath = mkOption { 127 type = types.path; 128 default = cfg.dataDir; 129 defaultText = lib.literalExpression "suwayomi-server.dataDir"; 130 example = "/var/data/local_mangas"; 131 description = '' 132 Path to the local source folder. 133 ''; 134 }; 135 136 systemTrayEnabled = mkOption { 137 type = types.bool; 138 default = false; 139 description = '' 140 Whether to enable a system tray icon, if possible. 141 ''; 142 }; 143 }; 144 }; 145 }; 146 description = '' 147 Configuration to write to {file}`server.conf`. 148 See <https://github.com/Suwayomi/Suwayomi-Server/wiki/Configuring-Suwayomi-Server> for more information. 149 ''; 150 default = { }; 151 example = { 152 server.socksProxyEnabled = true; 153 server.socksProxyHost = "yourproxyhost.com"; 154 server.socksProxyPort = "8080"; 155 }; 156 }; 157 }; 158 }; 159 160 config = mkIf cfg.enable { 161 162 assertions = [ 163 { 164 assertion = 165 with cfg.settings.server; 166 basicAuthEnabled -> (basicAuthUsername != null && basicAuthPasswordFile != null); 167 message = '' 168 [suwayomi-server]: the username and the password file cannot be null when the basic auth is enabled 169 ''; 170 } 171 ]; 172 173 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.server.port ]; 174 175 users.groups = mkIf (cfg.group == "suwayomi") { 176 suwayomi = { }; 177 }; 178 179 users.users = mkIf (cfg.user == "suwayomi") { 180 suwayomi = { 181 group = cfg.group; 182 # Need to set the user home because the package writes to ~/.local/Tachidesk 183 home = cfg.dataDir; 184 description = "Suwayomi Daemon user"; 185 isSystemUser = true; 186 }; 187 }; 188 189 systemd.tmpfiles.settings."10-suwayomi-server" = { 190 "${cfg.dataDir}/.local/share/Tachidesk".d = { 191 mode = "0700"; 192 inherit (cfg) user group; 193 }; 194 }; 195 196 systemd.services.suwayomi-server = 197 let 198 configFile = format.generate "server.conf" ( 199 lib.pipe cfg.settings [ 200 ( 201 settings: 202 lib.recursiveUpdate settings { 203 server.basicAuthPasswordFile = null; 204 server.basicAuthPassword = 205 if settings.server.basicAuthEnabled then "$TACHIDESK_SERVER_BASIC_AUTH_PASSWORD" else null; 206 } 207 ) 208 (lib.filterAttrsRecursive (_: x: x != null)) 209 ] 210 ); 211 in 212 { 213 description = "A free and open source manga reader server that runs extensions built for Tachiyomi."; 214 215 wantedBy = [ "multi-user.target" ]; 216 wants = [ "network-online.target" ]; 217 after = [ "network-online.target" ]; 218 219 script = '' 220 ${lib.optionalString cfg.settings.server.basicAuthEnabled '' 221 export TACHIDESK_SERVER_BASIC_AUTH_PASSWORD="$(<${cfg.settings.server.basicAuthPasswordFile})" 222 ''} 223 ${lib.getExe pkgs.envsubst} -i ${configFile} -o ${cfg.dataDir}/.local/share/Tachidesk/server.conf 224 ${lib.getExe cfg.package} -Dsuwayomi.tachidesk.config.server.rootDir=${cfg.dataDir} 225 ''; 226 227 serviceConfig = { 228 User = cfg.user; 229 Group = cfg.group; 230 231 Type = "simple"; 232 Restart = "on-failure"; 233 234 StateDirectory = mkIf (cfg.dataDir == "/var/lib/suwayomi-server") "suwayomi-server"; 235 }; 236 }; 237 }; 238 239 meta = { 240 maintainers = with lib.maintainers; [ ratcornu ]; 241 doc = ./suwayomi-server.md; 242 }; 243}