test
This commit is contained in:
@@ -12,7 +12,7 @@ let
|
||||
hostAddress = "10.0.1.3";
|
||||
actualUserId = config.users.users.nix-apps.uid;
|
||||
actualGroupId = config.users.groups.jallen-nas.gid;
|
||||
|
||||
|
||||
actualConfig =
|
||||
{ lib, ... }:
|
||||
{
|
||||
@@ -80,12 +80,12 @@ let
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
|
||||
bindMounts = {
|
||||
${dataDir} = {
|
||||
hostPath = cfg.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
bindMounts = {
|
||||
${dataDir} = {
|
||||
hostPath = cfg.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
|
||||
# Create reverse proxy configuration using mkReverseProxy
|
||||
reverseProxyConfig = lib.${namespace}.mkReverseProxy {
|
||||
@@ -95,23 +95,25 @@ let
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
};
|
||||
|
||||
actualContainer = (lib.${namespace}.mkContainer {
|
||||
name = "actual";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = actualConfig;
|
||||
}) { inherit lib; };
|
||||
actualContainer =
|
||||
(lib.${namespace}.mkContainer {
|
||||
name = "actual";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = actualConfig;
|
||||
})
|
||||
{ inherit lib; };
|
||||
|
||||
fullConfig = {
|
||||
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
|
||||
reverseProxies = [ reverseProxyConfig ];
|
||||
};
|
||||
} // actualContainer;
|
||||
}
|
||||
// actualContainer;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
|
||||
config = mkIf cfg.enable fullConfig;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.crowdsec;
|
||||
in
|
||||
@@ -71,6 +69,7 @@ in
|
||||
];
|
||||
};
|
||||
settings = {
|
||||
# general.api.server.enable = true;
|
||||
capi.credentialsFile = cfg.apiKey;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ let
|
||||
mailerPasswordFile = config.sops.secrets."jallen-nas/gitea/mail-key".path;
|
||||
metricsTokenFile = config.sops.secrets."jallen-nas/gitea/metrics-key".path;
|
||||
|
||||
serviceConfig =
|
||||
serviceConfig =
|
||||
{ lib, ... }:
|
||||
{
|
||||
services.gitea = {
|
||||
@@ -74,7 +74,7 @@ let
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
|
||||
|
||||
bindMounts = {
|
||||
${dataDir} = {
|
||||
hostPath = cfg.dataDir;
|
||||
@@ -95,19 +95,22 @@ let
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
};
|
||||
|
||||
containerConfig = (lib.${namespace}.mkContainer {
|
||||
name = "gitea";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.httpPort;
|
||||
bindMounts = bindMounts;
|
||||
config = serviceConfig;
|
||||
}) { inherit lib; };
|
||||
containerConfig =
|
||||
(lib.${namespace}.mkContainer {
|
||||
name = "gitea";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.httpPort;
|
||||
bindMounts = bindMounts;
|
||||
config = serviceConfig;
|
||||
})
|
||||
{ inherit lib; };
|
||||
|
||||
giteaConfig = {
|
||||
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
|
||||
reverseProxies = [ reverseProxyConfig ];
|
||||
};
|
||||
} // containerConfig;
|
||||
}
|
||||
// containerConfig;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, namespace, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) mkOpt mkReverseProxyOpt;
|
||||
cfg = config.${namespace}.services.glance;
|
||||
@@ -16,7 +21,7 @@ with lib;
|
||||
|
||||
reverseProxy = mkReverseProxyOpt;
|
||||
};
|
||||
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.glance = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, namespace, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) mkOpt mkReverseProxyOpt;
|
||||
cfg = config.${namespace}.services.matrix;
|
||||
@@ -19,10 +24,16 @@ let
|
||||
port = cfg.port;
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
bind_addresses = [ "::1" "0.0.0.0" ];
|
||||
bind_addresses = [
|
||||
"::1"
|
||||
"0.0.0.0"
|
||||
];
|
||||
resources = [
|
||||
{
|
||||
names = [ "client" "federation" ];
|
||||
names = [
|
||||
"client"
|
||||
"federation"
|
||||
];
|
||||
compress = false;
|
||||
}
|
||||
];
|
||||
@@ -37,7 +48,7 @@ let
|
||||
issuer = "https://authentik.mjallen.dev/application/o/matrix/";
|
||||
client_id = "KiChwyQn2kMtXU6LU0x3dlCb0jO6VB6e9xsN9NPs"; # TO BE FILLED
|
||||
client_secret = "6XRfNCUayZqnyaMv0QSEeFz98x2y8BkXnDyylmvAbg71YkQVtpEybP6jmPzncpJsx4k5evtziicgu8p9dOa2oADHL6Ao13643VMTsI4BSel1sbIICA2TH755BpB9J39A"; # TO BE FILLED
|
||||
scopes =[
|
||||
scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
@@ -64,31 +75,31 @@ let
|
||||
cp_max = 10;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
# Registration settings
|
||||
enable_registration = false; # Set to true initially to create admin user
|
||||
enable_registration = false; # Set to true initially to create admin user
|
||||
enable_registration_without_verification = false;
|
||||
# registration_shared_secret = "BogieDudie1";
|
||||
|
||||
|
||||
# Media settings
|
||||
max_upload_size = "50M";
|
||||
media_store_path = "/var/lib/matrix-synapse/media";
|
||||
|
||||
|
||||
# Logging
|
||||
# log_config = "/var/lib/matrix-synapse/log_config.yaml";
|
||||
trusted_key_servers = [
|
||||
{
|
||||
server_name = "matrix.org";
|
||||
server_name = "matrix.org";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
users.users.matrix-synapse = {
|
||||
isSystemUser = true;
|
||||
group = "matrix-synapse";
|
||||
};
|
||||
users.groups.matrix-synapse = {};
|
||||
users.groups.matrix-synapse = { };
|
||||
|
||||
services.postgresql = {
|
||||
enable = lib.mkDefault true;
|
||||
@@ -135,19 +146,22 @@ let
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
};
|
||||
|
||||
matrixContainer = (lib.${namespace}.mkContainer {
|
||||
name = "matrix-synapse";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = matrixConfig;
|
||||
}) { inherit lib; };
|
||||
matrixContainer =
|
||||
(lib.${namespace}.mkContainer {
|
||||
name = "matrix-synapse";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = matrixConfig;
|
||||
})
|
||||
{ inherit lib; };
|
||||
|
||||
fullConfig = {
|
||||
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
|
||||
reverseProxies = [ reverseProxyConfig ];
|
||||
};
|
||||
} // matrixContainer;
|
||||
}
|
||||
// matrixContainer;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
@@ -164,4 +178,4 @@ with lib;
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable fullConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,24 +96,28 @@ in
|
||||
secretFile = secretsFile;
|
||||
|
||||
extraApps = {
|
||||
inherit (pkgs.nextcloud31Packages.apps) app_api
|
||||
bookmarks
|
||||
mail
|
||||
calendar
|
||||
contacts
|
||||
integration_openai
|
||||
integration_paperless
|
||||
maps
|
||||
oidc_login
|
||||
onlyoffice
|
||||
previewgenerator
|
||||
recognize
|
||||
richdocuments
|
||||
user_oidc;
|
||||
inherit (pkgs.nextcloud31Packages.apps)
|
||||
app_api
|
||||
bookmarks
|
||||
mail
|
||||
calendar
|
||||
contacts
|
||||
integration_openai
|
||||
integration_paperless
|
||||
maps
|
||||
oidc_login
|
||||
onlyoffice
|
||||
previewgenerator
|
||||
recognize
|
||||
richdocuments
|
||||
user_oidc
|
||||
;
|
||||
|
||||
inherit nextcloudPhotos
|
||||
nextcloudPdfViewer
|
||||
nextcloudAssist;
|
||||
inherit
|
||||
nextcloudPhotos
|
||||
nextcloudPdfViewer
|
||||
nextcloudAssist
|
||||
;
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{ config, lib, namespace, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib.${namespace}) mkOpt mkReverseProxyOpt;
|
||||
cfg = config.${namespace}.services.ntfy;
|
||||
@@ -66,19 +71,22 @@ let
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
};
|
||||
|
||||
ntfyContainer = (lib.${namespace}.mkContainer {
|
||||
name = "ntfy";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = ntfyConfig;
|
||||
}) { inherit lib; };
|
||||
ntfyContainer =
|
||||
(lib.${namespace}.mkContainer {
|
||||
name = "ntfy";
|
||||
localAddress = cfg.localAddress;
|
||||
port = cfg.port;
|
||||
bindMounts = bindMounts;
|
||||
config = ntfyConfig;
|
||||
})
|
||||
{ inherit lib; };
|
||||
|
||||
fullConfig = {
|
||||
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
|
||||
reverseProxies = [ reverseProxyConfig ];
|
||||
};
|
||||
} // ntfyContainer;
|
||||
}
|
||||
// ntfyContainer;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
# Tabby Web Service Module
|
||||
|
||||
This module provides a NixOS service for running the Tabby Web terminal application server.
|
||||
|
||||
## Features
|
||||
|
||||
- Systemd service with automatic startup
|
||||
- User and group management
|
||||
- Database migration on startup
|
||||
- Configurable environment variables
|
||||
- Security hardening
|
||||
- Firewall integration
|
||||
- Support for PostgreSQL and SQLite databases
|
||||
- Social authentication configuration
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```nix
|
||||
{
|
||||
mjallen.services.tabby-web = {
|
||||
enable = true;
|
||||
port = 9000;
|
||||
openFirewall = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
```nix
|
||||
{
|
||||
mjallen.services.tabby-web = {
|
||||
enable = true;
|
||||
port = 8080;
|
||||
openFirewall = true;
|
||||
|
||||
# Use PostgreSQL instead of SQLite
|
||||
databaseUrl = "postgresql://tabby:password@localhost:5432/tabby";
|
||||
|
||||
# Use S3 for app distribution storage
|
||||
appDistStorage = "s3://my-bucket/tabby-dist";
|
||||
|
||||
# Configure social authentication
|
||||
socialAuth = {
|
||||
github = {
|
||||
key = "your-github-oauth-key";
|
||||
secret = "your-github-oauth-secret";
|
||||
};
|
||||
gitlab = {
|
||||
key = "your-gitlab-oauth-key";
|
||||
secret = "your-gitlab-oauth-secret";
|
||||
};
|
||||
};
|
||||
|
||||
# Performance tuning
|
||||
workers = 8;
|
||||
timeout = 300;
|
||||
|
||||
# Additional environment variables
|
||||
extraEnvironment = {
|
||||
DEBUG = "0";
|
||||
LOG_LEVEL = "info";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Basic Options
|
||||
|
||||
- `enable`: Enable the tabby-web service
|
||||
- `port`: Port to run the server on (default: 9000)
|
||||
- `openFirewall`: Whether to open the firewall port (default: false)
|
||||
- `user`: User to run the service as (default: "tabby-web")
|
||||
- `group`: Group to run the service as (default: "tabby-web")
|
||||
- `dataDir`: Data directory (default: "/var/lib/tabby-web")
|
||||
|
||||
### Database Configuration
|
||||
|
||||
- `databaseUrl`: Database connection URL
|
||||
- SQLite: `"sqlite:///var/lib/tabby-web/tabby.db"` (default)
|
||||
- PostgreSQL: `"postgresql://user:password@host:port/database"`
|
||||
|
||||
### Storage Configuration
|
||||
|
||||
- `appDistStorage`: Storage URL for app distributions
|
||||
- Local: `"file:///var/lib/tabby-web/dist"` (default)
|
||||
- S3: `"s3://bucket-name/path"`
|
||||
- GCS: `"gcs://bucket-name/path"`
|
||||
|
||||
### Social Authentication
|
||||
|
||||
Configure OAuth providers:
|
||||
|
||||
```nix
|
||||
socialAuth = {
|
||||
github = {
|
||||
key = "oauth-key";
|
||||
secret = "oauth-secret";
|
||||
};
|
||||
gitlab = {
|
||||
key = "oauth-key";
|
||||
secret = "oauth-secret";
|
||||
};
|
||||
microsoftGraph = {
|
||||
key = "oauth-key";
|
||||
secret = "oauth-secret";
|
||||
};
|
||||
googleOauth2 = {
|
||||
key = "oauth-key";
|
||||
secret = "oauth-secret";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Performance Options
|
||||
|
||||
- `workers`: Number of gunicorn worker processes (default: 4)
|
||||
- `timeout`: Worker timeout in seconds (default: 120)
|
||||
|
||||
### Additional Configuration
|
||||
|
||||
- `extraEnvironment`: Additional environment variables as an attribute set
|
||||
|
||||
## Service Management
|
||||
|
||||
```bash
|
||||
# Start the service
|
||||
sudo systemctl start tabby-web
|
||||
|
||||
# Enable automatic startup
|
||||
sudo systemctl enable tabby-web
|
||||
|
||||
# Check service status
|
||||
sudo systemctl status tabby-web
|
||||
|
||||
# View logs
|
||||
sudo journalctl -u tabby-web -f
|
||||
|
||||
# Run management commands
|
||||
sudo -u tabby-web tabby-web-manage migrate
|
||||
sudo -u tabby-web tabby-web-manage add_version 1.0.156-nightly.2
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
The service runs with extensive security hardening:
|
||||
|
||||
- Dedicated user and group
|
||||
- Restricted filesystem access
|
||||
- No new privileges
|
||||
- Protected system directories
|
||||
- Private temporary directory
|
||||
- Memory execution protection
|
||||
- Namespace restrictions
|
||||
|
||||
## Database Setup
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
If using PostgreSQL, ensure the database and user exist:
|
||||
|
||||
```sql
|
||||
CREATE USER tabby WITH PASSWORD 'your-password';
|
||||
CREATE DATABASE tabby OWNER tabby;
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
SQLite databases are created automatically in the data directory.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **Service fails to start**: Check logs with `journalctl -u tabby-web`
|
||||
2. **Database connection issues**: Verify database URL and credentials
|
||||
3. **Permission errors**: Ensure data directory has correct ownership
|
||||
4. **Port conflicts**: Check if another service is using the configured port
|
||||
|
||||
## Integration with Reverse Proxy
|
||||
|
||||
Example Nginx configuration:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name tabby.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:9000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.tabby-web;
|
||||
|
||||
# Build environment variables from configuration
|
||||
environmentVars = {
|
||||
DATABASE_URL = cfg.databaseUrl;
|
||||
APP_DIST_STORAGE = cfg.appDistStorage;
|
||||
PORT = toString cfg.port;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.github.key != null) {
|
||||
SOCIAL_AUTH_GITHUB_KEY = cfg.socialAuth.github.key;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.github.secret != null) {
|
||||
SOCIAL_AUTH_GITHUB_SECRET = cfg.socialAuth.github.secret;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.gitlab.key != null) {
|
||||
SOCIAL_AUTH_GITLAB_KEY = cfg.socialAuth.gitlab.key;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.gitlab.secret != null) {
|
||||
SOCIAL_AUTH_GITLAB_SECRET = cfg.socialAuth.gitlab.secret;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.microsoftGraph.key != null) {
|
||||
SOCIAL_AUTH_MICROSOFT_GRAPH_KEY = cfg.socialAuth.microsoftGraph.key;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.microsoftGraph.secret != null) {
|
||||
SOCIAL_AUTH_MICROSOFT_GRAPH_SECRET = cfg.socialAuth.microsoftGraph.secret;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.googleOauth2.key != null) {
|
||||
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = cfg.socialAuth.googleOauth2.key;
|
||||
}
|
||||
// optionalAttrs (cfg.socialAuth.googleOauth2.secret != null) {
|
||||
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = cfg.socialAuth.googleOauth2.secret;
|
||||
}
|
||||
// cfg.extraEnvironment;
|
||||
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Create user and group
|
||||
users.users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
description = "Tabby Web service user";
|
||||
};
|
||||
|
||||
users.groups.${cfg.group} = { };
|
||||
|
||||
# Ensure data directory exists with correct permissions
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d '${cfg.dataDir}/dist' 0750 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
|
||||
# Create the systemd service
|
||||
systemd.services.tabby-web = {
|
||||
description = "Tabby Web Terminal Application Server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ] ++ optional (hasPrefix "postgresql://" cfg.databaseUrl) "postgresql.service";
|
||||
|
||||
environment = environmentVars;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
|
||||
# Use the tabby-web package from our custom packages
|
||||
ExecStart = "${pkgs.${namespace}.tabby-web}/bin/tabby-web --workers ${toString cfg.workers} --timeout ${toString cfg.timeout}";
|
||||
|
||||
# Run database migrations before starting the service
|
||||
ExecStartPre = "${pkgs.${namespace}.tabby-web}/bin/tabby-web-manage migrate";
|
||||
|
||||
# Security settings
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ReadWritePaths = [ cfg.dataDir ];
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
||||
# Restart policy
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE = "65536";
|
||||
};
|
||||
|
||||
# Ensure the service starts after database if using PostgreSQL
|
||||
requisite = mkIf (hasPrefix "postgresql://" cfg.databaseUrl) [ "postgresql.service" ];
|
||||
};
|
||||
|
||||
# Open firewall if requested
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
# Add the tabby-web package to system packages
|
||||
environment.systemPackages = [ pkgs.${namespace}.tabby-web ];
|
||||
};
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
# Example configuration for Tabby Web service
|
||||
# Add this to your NixOS configuration to enable tabby-web
|
||||
|
||||
{
|
||||
# Basic configuration - SQLite database, local storage
|
||||
mjallen.services.tabby-web = {
|
||||
enable = true;
|
||||
port = 9000;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
# Advanced configuration example (commented out)
|
||||
/*
|
||||
mjallen.services.tabby-web = {
|
||||
enable = true;
|
||||
port = 8080;
|
||||
openFirewall = true;
|
||||
|
||||
# Use PostgreSQL database
|
||||
databaseUrl = "postgresql://tabby:password@localhost:5432/tabby";
|
||||
|
||||
# Use S3 for app distribution storage
|
||||
appDistStorage = "s3://my-bucket/tabby-dist";
|
||||
|
||||
# Configure GitHub OAuth
|
||||
socialAuth.github = {
|
||||
key = "your-github-oauth-key";
|
||||
secret = "your-github-oauth-secret";
|
||||
};
|
||||
|
||||
# Performance tuning
|
||||
workers = 8;
|
||||
timeout = 300;
|
||||
|
||||
# Custom data directory
|
||||
dataDir = "/srv/tabby-web";
|
||||
|
||||
# Additional environment variables
|
||||
extraEnvironment = {
|
||||
DEBUG = "0";
|
||||
LOG_LEVEL = "info";
|
||||
};
|
||||
};
|
||||
*/
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.tabby-web = {
|
||||
enable = mkEnableOption "Tabby Web terminal application server";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 9000;
|
||||
description = "Port for tabby-web server";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to open firewall for tabby-web";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "tabby-web";
|
||||
description = "User to run tabby-web as";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "tabby-web";
|
||||
description = "Group to run tabby-web as";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/tabby-web";
|
||||
description = "Directory to store tabby-web data";
|
||||
};
|
||||
|
||||
databaseUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "sqlite:///var/lib/tabby-web/tabby.db";
|
||||
description = "Database connection URL";
|
||||
example = "postgresql://user:password@localhost:5432/tabby";
|
||||
};
|
||||
|
||||
appDistStorage = mkOption {
|
||||
type = types.str;
|
||||
default = "file:///var/lib/tabby-web/dist";
|
||||
description = "Storage URL for app distributions";
|
||||
example = "s3://my-bucket/tabby-dist";
|
||||
};
|
||||
|
||||
socialAuth = {
|
||||
github = {
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "GitHub OAuth key";
|
||||
};
|
||||
secret = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "GitHub OAuth secret";
|
||||
};
|
||||
};
|
||||
|
||||
gitlab = {
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "GitLab OAuth key";
|
||||
};
|
||||
secret = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "GitLab OAuth secret";
|
||||
};
|
||||
};
|
||||
|
||||
microsoftGraph = {
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Microsoft Graph OAuth key";
|
||||
};
|
||||
secret = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Microsoft Graph OAuth secret";
|
||||
};
|
||||
};
|
||||
|
||||
googleOauth2 = {
|
||||
key = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Google OAuth2 key";
|
||||
};
|
||||
secret = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Google OAuth2 secret";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraEnvironment = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Extra environment variables for tabby-web";
|
||||
example = {
|
||||
DEBUG = "1";
|
||||
LOG_LEVEL = "info";
|
||||
};
|
||||
};
|
||||
|
||||
workers = mkOption {
|
||||
type = types.ints.positive;
|
||||
default = 4;
|
||||
description = "Number of gunicorn worker processes";
|
||||
};
|
||||
|
||||
timeout = mkOption {
|
||||
type = types.ints.positive;
|
||||
default = 120;
|
||||
description = "Worker timeout in seconds";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -9,42 +9,46 @@ let
|
||||
cfg = config.${namespace}.services.traefik;
|
||||
|
||||
# Process extraServices into service configurations
|
||||
extraServiceConfigs =
|
||||
extraServiceConfigs =
|
||||
let
|
||||
makeService = service: nameValuePair service.name {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = service.url;
|
||||
}
|
||||
];
|
||||
};
|
||||
makeService =
|
||||
service:
|
||||
nameValuePair service.name {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = service.url;
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
listToAttrs (map makeService cfg.extraServices);
|
||||
|
||||
# Process extraRouters into router configurations
|
||||
extraRouterConfigs =
|
||||
extraRouterConfigs =
|
||||
let
|
||||
makeRouter = router: nameValuePair router.subdomain {
|
||||
entryPoints = router.entryPoints;
|
||||
rule = "Host(`${router.subdomain}.${domain}`)";
|
||||
service = router.service;
|
||||
middlewares = router.middlewares ++ [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
makeRouter =
|
||||
router:
|
||||
nameValuePair router.subdomain {
|
||||
entryPoints = router.entryPoints;
|
||||
rule = "Host(`${router.subdomain}.${domain}`)";
|
||||
service = router.service;
|
||||
middlewares = router.middlewares ++ [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
in
|
||||
listToAttrs (map makeRouter cfg.extraRouters);
|
||||
|
||||
# Process reverseProxies into service and router configurations
|
||||
reverseProxyServiceConfigs =
|
||||
reverseProxyServiceConfigs =
|
||||
let
|
||||
makeService = reverseProxy: nameValuePair reverseProxy.service.name reverseProxy.service.config;
|
||||
in
|
||||
listToAttrs (map makeService cfg.reverseProxies);
|
||||
|
||||
reverseProxyRouterConfigs =
|
||||
reverseProxyRouterConfigs =
|
||||
let
|
||||
makeRouter = reverseProxy: nameValuePair reverseProxy.router.subdomain reverseProxy.router.config;
|
||||
in
|
||||
@@ -292,7 +296,7 @@ in
|
||||
url = authUrl;
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
authentik.loadBalancer.servers = [
|
||||
{
|
||||
url = authentikUrl;
|
||||
@@ -348,7 +352,9 @@ in
|
||||
url = paperlessUrl;
|
||||
}
|
||||
];
|
||||
} // extraServiceConfigs // reverseProxyServiceConfigs;
|
||||
}
|
||||
// extraServiceConfigs
|
||||
// reverseProxyServiceConfigs;
|
||||
|
||||
routers = {
|
||||
auth = {
|
||||
@@ -457,7 +463,9 @@ in
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
} // extraRouterConfigs // reverseProxyRouterConfigs;
|
||||
}
|
||||
// extraRouterConfigs
|
||||
// reverseProxyRouterConfigs;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
let
|
||||
inherit (lib.${namespace}) mkOpt mkBoolOpt;
|
||||
inherit (lib.${namespace}) mkOpt;
|
||||
in
|
||||
{
|
||||
options.${namespace}.services.traefik = {
|
||||
enable = mkEnableOption "enable traefik";
|
||||
|
||||
extraServices = mkOpt (types.listOf (types.submodule {
|
||||
options = {
|
||||
name = mkOpt types.str "" "Name of the service";
|
||||
url = mkOpt types.str "http://localhost:8080" "Url of the service";
|
||||
};
|
||||
})) [ ] "List of extra services to forward";
|
||||
extraServices = mkOpt (types.listOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
name = mkOpt types.str "" "Name of the service";
|
||||
url = mkOpt types.str "http://localhost:8080" "Url of the service";
|
||||
};
|
||||
}
|
||||
)) [ ] "List of extra services to forward";
|
||||
|
||||
extraRouters = mkOpt (types.listOf (types.submodule {
|
||||
options = {
|
||||
entryPoints = mkOpt (types.listOf types.str) [ "websecure" ] "Entrypoint";
|
||||
subdomain = mkOpt types.str "" "subdomain of the service";
|
||||
service = mkOpt types.str "" "name of the service";
|
||||
middlewares = mkOpt (types.listOf (types.enum [
|
||||
"authentik"
|
||||
"onlyoffice-websocket"
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"internal-ipallowlist"
|
||||
])) [ ] "List of middlewares to enable";
|
||||
};
|
||||
})) [ ] "List of extra services to forward";
|
||||
extraRouters = mkOpt (types.listOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
entryPoints = mkOpt (types.listOf types.str) [ "websecure" ] "Entrypoint";
|
||||
subdomain = mkOpt types.str "" "subdomain of the service";
|
||||
service = mkOpt types.str "" "name of the service";
|
||||
middlewares = mkOpt (types.listOf (
|
||||
types.enum [
|
||||
"authentik"
|
||||
"onlyoffice-websocket"
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"internal-ipallowlist"
|
||||
]
|
||||
)) [ ] "List of middlewares to enable";
|
||||
};
|
||||
}
|
||||
)) [ ] "List of extra services to forward";
|
||||
|
||||
reverseProxies = mkOpt (types.listOf types.attrs) [ ] "List of reverse proxy configurations from mkReverseProxy";
|
||||
reverseProxies =
|
||||
mkOpt (types.listOf types.attrs) [ ]
|
||||
"List of reverse proxy configurations from mkReverseProxy";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ in
|
||||
uri = "tcp://0.0.0.0:10300";
|
||||
};
|
||||
|
||||
piper = {
|
||||
package = pkgs.stable.wyoming-piper;
|
||||
servers.hass-piper = {
|
||||
enable = true;
|
||||
voice = "en-us-ryan-high";
|
||||
uri = "tcp://0.0.0.0:10200";
|
||||
};
|
||||
};
|
||||
# piper = {
|
||||
# package = pkgs.stable.wyoming-piper;
|
||||
# servers.hass-piper = {
|
||||
# enable = true;
|
||||
# voice = "en-us-ryan-high";
|
||||
# uri = "tcp://0.0.0.0:10200";
|
||||
# };
|
||||
# };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user