- 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)
526 lines
8.7 KiB
Markdown
526 lines
8.7 KiB
Markdown
# 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
|