docs: update zellij-ps to reflect project switcher functionality

- Update package description and fix mainProgram typo
- Rewrite documentation to describe project switching, not process viewing
- Add PROJECT_FOLDERS configuration and usage examples
- Update all references across docs (README, guides, module overviews)
This commit is contained in:
m3tm3re
2025-12-30 15:42:52 +01:00
parent 744b6a8243
commit 44485c4c72
28 changed files with 8096 additions and 24 deletions

View File

@@ -0,0 +1,525 @@
# Port Management Guide
Managing service ports across multiple hosts with the `m3ta.ports` module.
## Overview
The port management module provides a centralized way to define service ports that can have host-specific overrides. This prevents port conflicts and makes it easy to manage services across multiple machines.
## Basic Usage
### Enable Port Management
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
# Define default ports
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
homepage = 8080;
};
# Define host-specific overrides
hostOverrides = {
laptop = {
nginx = 8080; # Override on laptop
homepage = 3001; # Override on laptop
};
server = {
homepage = 3002; # Override on server
};
};
# Set current host (determines which overrides to use)
currentHost = config.networking.hostName;
};
}
```
### Using Ports
```nix
{config, ...}: {
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
}
```
## Module Options
### `m3ta.ports.enable`
Enable port management module.
- Type: `boolean`
- Default: `false`
### `m3ta.ports.definitions`
Default port definitions.
- Type: `attrsOf int`
- Default: `{}`
```nix
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
};
```
### `m3ta.ports.hostOverrides`
Host-specific port overrides.
- Type: `attrsOf (attrsOf int)`
- Default: `{}`
```nix
hostOverrides = {
laptop = {
nginx = 8080;
grafana = 3001;
};
server = {
grafana = 3002;
};
};
```
### `m3ta.ports.currentHost`
Current hostname. Determines which overrides to apply.
- Type: `string`
- Example: `config.networking.hostName`
```nix
currentHost = "laptop"; # Use laptop overrides
```
### `m3ta.ports.generateEnvVars` (Home Manager only)
Generate environment variables from ports.
- Type: `boolean`
- Default: `false` (Home Manager)
- NixOS: Not available
When enabled, generates environment variables like:
- `PORT_NGINX=8080`
- `PORT_GRAFANA=3000`
## Functions
### `config.m3ta.ports.get "service"`
Get port for a service with host-specific override.
```nix
services.nginx = {
port = config.m3ta.ports.get "nginx";
};
```
If current host is `laptop` and `hostOverrides.laptop.nginx = 8080`, returns `8080`.
If no override, returns default `80`.
### `config.m3ta.ports.getHostPorts "hostname"`
Get all ports for a specific host.
```nix
# Get all ports for laptop
laptopPorts = config.m3ta.ports.getHostPorts "laptop";
# Returns: { nginx = 8080; grafana = 3000; ... }
```
### `config.m3ta.ports.listServices`
List all defined service names.
```nix
allServices = config.m3ta.ports.listServices;
# Returns: ["nginx" "grafana" "prometheus" "homepage"]
```
## Examples
### NixOS Configuration
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
prometheus = 9090;
loki = 3100;
promtail = 9080;
};
hostOverrides.laptop = {
nginx = 8080;
grafana = 3001;
};
currentHost = config.networking.hostName;
};
# Use ports
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
root /var/www;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
services.prometheus = {
enable = true;
port = config.m3ta.ports.get "prometheus";
};
services.loki = {
enable = true;
configuration.http_listen_port = config.m3ta.ports.get "loki";
};
}
```
### Home Manager Configuration
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
dev-server = 3000;
nextjs = 3001;
vite = 5173;
};
hostOverrides.desktop = {
vite = 5174;
};
currentHost = "desktop";
generateEnvVars = true; # Generate env vars
};
# Ports are now available as env vars
# PORT_DEV_SERVER=3000
# PORT_NEXTJS=3001
# PORT_VITE=5174
home.sessionVariables = {
DEV_PORT = toString (config.m3ta.ports.get "dev-server");
};
}
```
### With Custom Modules
Using ports with custom modules (e.g., `m3ta.mem0`):
```nix
{config, ...}: {
# Define ports
m3ta.ports = {
enable = true;
definitions = {
mem0 = 8000;
qdrant = 6333;
};
hostOverrides.laptop = {
mem0 = 8080;
};
currentHost = config.networking.hostName;
};
# Use with mem0 module
m3ta.mem0 = {
enable = true;
port = config.m3ta.ports.get "mem0"; # 8000 or 8080 on laptop
};
# Use with qdrant service
services.qdrant = {
enable = true;
port = config.m3ta.ports.get "qdrant";
};
}
```
### Port File Generation
Generate a JSON file with all ports:
```nix
{config, pkgs, ...}: {
m3ta.ports = {
enable = true;
definitions = {
service1 = 80;
service2 = 443;
};
currentHost = config.networking.hostName;
};
# Generate port file
environment.etc."m3ta/ports.json".text = builtins.toJSON (
config.m3ta.ports.getHostPorts config.networking.hostName
);
}
```
## Advanced Usage
### Conditional Configuration
```nix
{config, ...}: {
services.nginx = {
enable = true;
# Only open firewall if binding to non-localhost
httpConfig = let
port = config.m3ta.ports.get "nginx";
in ''
server {
listen ${toString port};
}
'';
};
networking.firewall.allowedTCPPorts =
if config.m3ta.ports.get "nginx" == 80
then [80]
else [];
}
```
### Port Ranges
```nix
definitions = {
service-start = 8000;
service-end = 8999;
};
# Use in config
services.my-app = {
portRange = [
config.m3ta.ports.get "service-start"
config.m3ta.ports.get "service-end"
];
};
```
### Dynamic Port Allocation
```nix
{config, ...}: {
m3ta.ports = {
enable = true;
definitions = {
# Reserve port ranges
app-range-start = 9000;
app-range-end = 9999;
};
currentHost = config.networking.hostName;
};
# Calculate next available port
services.my-app = {
port = config.m3ta.ports.get "app-range-start" + 0;
};
services.my-other-app = {
port = config.m3ta.ports.get "app-range-start" + 1;
};
}
```
## Best Practices
### Use Descriptive Service Names
```nix
# Good
definitions = {
nginx = 80;
grafana = 3000;
prometheus-ui = 9090;
prometheus-push = 9091;
};
# Avoid
definitions = {
p1 = 80;
p2 = 3000;
p3 = 9090;
};
```
### Group Related Services
```nix
definitions = {
# Monitoring stack
grafana = 3000;
prometheus = 9090;
loki = 3100;
promtail = 9080;
# Web services
nginx = 80;
homepage = 8080;
# Databases
postgres = 5432;
redis = 6379;
qdrant = 6333;
};
```
### Document Overrides
```nix
hostOverrides = {
# Laptop: Running multiple dev servers, use higher ports
laptop = {
nginx = 8080;
dev-server = 3000;
};
# Server: Production, use standard ports
server = {
nginx = 80;
dev-server = null; # Disable on server
};
};
```
### Handle Missing Ports
```nix
services.some-service = {
enable = true;
port = config.m3ta.ports.get "some-service" or 8080;
};
```
## Troubleshooting
### Service Not Found
Error: `Service "foo" not defined`
Solution: Add service to `definitions`:
```nix
definitions = {
foo = 8080;
};
```
### Current Host Not Set
Error: `currentHost not set`
Solution: Set `currentHost`:
```nix
currentHost = config.networking.hostName;
```
### Port Conflict
Issue: Two services trying to use same port.
Solution: Define both in port management:
```nix
definitions = {
service1 = 8080;
service2 = 8081; # Different port
};
```
## Migration from Hardcoded Ports
### Before
```nix
services.nginx = {
enable = true;
httpConfig = ''
server {
listen 80;
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = 3000;
};
```
### After
```nix
m3ta.ports = {
enable = true;
definitions = {
nginx = 80;
grafana = 3000;
};
currentHost = config.networking.hostName;
};
services.nginx = {
enable = true;
httpConfig = ''
server {
listen ${toString (config.m3ta.ports.get "nginx")};
}
'';
};
services.grafana = {
enable = true;
settings.server.http_port = config.m3ta.ports.get "grafana";
};
```
## Next Steps
- [Architecture](../ARCHITECTURE.md) - Understanding the library functions
- [Using Modules](./using-modules.md) - Using modules with port management
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines