fix: user systemd
This commit is contained in:
+103
-66
@@ -9,6 +9,7 @@ The role also performs required kernel tuning for optimal Valkey performance.
|
||||
Valkey is a high-performance key/value datastore and a drop-in replacement for Redis. It was created as a community-driven fork after Redis changed its license from BSD to proprietary licenses (RSALv2 and SSPLv1) in March 2024.
|
||||
|
||||
**Key points:**
|
||||
|
||||
- Valkey is 100% API-compatible with Redis
|
||||
- Backed by the Linux Foundation
|
||||
- Uses permissive open-source license (BSD 3-Clause)
|
||||
@@ -16,6 +17,7 @@ Valkey is a high-performance key/value datastore and a drop-in replacement for R
|
||||
- Same commands, same protocol, same performance
|
||||
|
||||
**Distribution support:**
|
||||
|
||||
- **Arch Linux**: Installs Valkey (redis package replaced in April 2024)
|
||||
- **Debian/Ubuntu**: Installs Valkey from official repositories
|
||||
|
||||
@@ -58,9 +60,10 @@ Valkey binds to `127.0.0.1` by default (secure, localhost-only).
|
||||
Containers can reach Valkey via Pasta's `--map-host-loopback` feature, which routes container's `127.0.0.1` to the host's `127.0.0.1`.
|
||||
|
||||
In docker-compose files, use:
|
||||
|
||||
```yaml
|
||||
extra_hosts:
|
||||
- "host.containers.internal:127.0.0.1"
|
||||
- "host.containers.internal:127.0.0.1"
|
||||
```
|
||||
|
||||
No additional bind addresses needed!
|
||||
@@ -78,8 +81,8 @@ None.
|
||||
- hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- role: valkey
|
||||
- role: immich # Will connect to system Valkey
|
||||
- role: valkey
|
||||
- role: immich # Will connect to system Valkey
|
||||
```
|
||||
|
||||
### Custom Configuration with ACL Users
|
||||
@@ -89,25 +92,26 @@ None.
|
||||
- hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- role: valkey
|
||||
vars:
|
||||
valkey_admin_password: "{{ vault_valkey_password }}"
|
||||
valkey_maxmemory: 512mb
|
||||
valkey_maxmemory_policy: volatile-lru
|
||||
valkey_acl_users:
|
||||
- username: immich
|
||||
password: "{{ immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
- username: nextcloud
|
||||
password: "{{ nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info"
|
||||
- role: valkey
|
||||
vars:
|
||||
valkey_admin_password: "{{ vault_valkey_password }}"
|
||||
valkey_maxmemory: 512mb
|
||||
valkey_maxmemory_policy: volatile-lru
|
||||
valkey_acl_users:
|
||||
- username: immich
|
||||
password: "{{ immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
- username: nextcloud
|
||||
password: "{{ nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info"
|
||||
```
|
||||
|
||||
## How Services Connect
|
||||
|
||||
Services running on the same host can connect to Valkey at:
|
||||
|
||||
- **Host**: `localhost` or `127.0.0.1`
|
||||
- **Port**: `6379` (default)
|
||||
|
||||
@@ -116,6 +120,7 @@ Services running on the same host can connect to Valkey at:
|
||||
Containers need special handling to reach the host's Valkey:
|
||||
|
||||
**Use `host.containers.internal`:**
|
||||
|
||||
```yaml
|
||||
REDIS_HOSTNAME: host.containers.internal
|
||||
REDIS_PORT: 6379
|
||||
@@ -135,6 +140,7 @@ This special DNS name resolves to the host machine from inside containers.
|
||||
### ACL-Based Authentication
|
||||
|
||||
This role uses Valkey's ACL (Access Control List) system for fine-grained security. Each service gets:
|
||||
|
||||
- **Dedicated credentials**: Unique username and password
|
||||
- **Key pattern restrictions**: Can only access specific key patterns
|
||||
- **Command restrictions**: Limited to required commands only
|
||||
@@ -149,25 +155,26 @@ Define ACL users in your inventory or host_vars:
|
||||
valkey_admin_password: "your-strong-admin-password"
|
||||
|
||||
valkey_acl_users:
|
||||
- username: immich
|
||||
password: "{{ immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
|
||||
- username: nextcloud
|
||||
password: "{{ nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info"
|
||||
|
||||
- username: gitea
|
||||
password: "{{ gitea_valkey_password }}"
|
||||
keypattern: "gitea*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
- username: immich
|
||||
password: "{{ immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
|
||||
- username: nextcloud
|
||||
password: "{{ nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info"
|
||||
|
||||
- username: gitea
|
||||
password: "{{ gitea_valkey_password }}"
|
||||
keypattern: "gitea*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
```
|
||||
|
||||
### ACL Configuration Guide
|
||||
|
||||
**Key Pattern (`keypattern`):**
|
||||
|
||||
- Single pattern: `"myservice*"` - matches keys starting with `myservice`
|
||||
- Multiple patterns: `"pattern1* pattern2*"` - space-separated (automatically converted to `~pattern1* ~pattern2*` in ACL file)
|
||||
- All keys: `"*"` - not recommended for security
|
||||
@@ -179,17 +186,21 @@ valkey_acl_users:
|
||||
The role automatically configures kernel parameters required by Valkey (see `tasks/kernel-tuning.yml`):
|
||||
|
||||
**1. Memory Overcommit:**
|
||||
|
||||
```
|
||||
vm.overcommit_memory = 1
|
||||
```
|
||||
|
||||
- Required for background saves and replication
|
||||
- Configured via `/etc/sysctl.conf`
|
||||
- Applied immediately and persists across reboots
|
||||
|
||||
**2. Transparent Huge Pages (THP):**
|
||||
|
||||
```
|
||||
transparent_hugepage=madvise
|
||||
```
|
||||
|
||||
- Reduces latency and memory usage issues
|
||||
- Safely appended to existing GRUB kernel parameters (does not overwrite)
|
||||
- Only adds parameter if `transparent_hugepage=` is not already present
|
||||
@@ -202,6 +213,7 @@ These settings are required to eliminate Valkey startup warnings and ensure opti
|
||||
**Note:** The role preserves existing GRUB parameters. If you have `GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"`, it will become `GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet transparent_hugepage=madvise"`.
|
||||
|
||||
**Commands (`commands`):**
|
||||
|
||||
- `&*` - Allow all pub/sub channels (required for job queues like BullMQ)
|
||||
- `+allchannels` - Alternative to `&*`
|
||||
- `+@read` - Allow all read commands (GET, MGET, etc.)
|
||||
@@ -213,14 +225,15 @@ These settings are required to eliminate Valkey startup warnings and ensure opti
|
||||
|
||||
**Common Command Sets:**
|
||||
|
||||
| Service Type | Recommended Commands |
|
||||
|-------------|---------------------|
|
||||
| **Simple cache** | `+@read +@write -@dangerous +auth +ping +info` |
|
||||
| **Session store** | `+@read +@write -@dangerous +auth +ping +info +select` |
|
||||
| Service Type | Recommended Commands |
|
||||
| ---------------------- | --------------------------------------------------------------------------------- |
|
||||
| **Simple cache** | `+@read +@write -@dangerous +auth +ping +info` |
|
||||
| **Session store** | `+@read +@write -@dangerous +auth +ping +info +select` |
|
||||
| **Job queue (BullMQ)** | `&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha` |
|
||||
| **Pub/sub** | `+@pubsub +@read +@write -@dangerous +auth +ping +info` |
|
||||
| **Pub/sub** | `+@pubsub +@read +@write -@dangerous +auth +ping +info` |
|
||||
|
||||
**Security Best Practices:**
|
||||
|
||||
- Always include `-@dangerous` to prevent accidental data loss
|
||||
- Use specific key patterns to isolate services
|
||||
- Only grant `+eval` and `+evalsha` if required (job queues)
|
||||
@@ -244,12 +257,12 @@ Add encrypted values to your inventory:
|
||||
|
||||
```yaml
|
||||
valkey_admin_password: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
...
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
...
|
||||
|
||||
immich_valkey_password: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
...
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
...
|
||||
```
|
||||
|
||||
## Service Management
|
||||
@@ -275,6 +288,7 @@ valkey-cli # Also available on Arch Linux
|
||||
## Persistence
|
||||
|
||||
Valkey is configured with RDB persistence:
|
||||
|
||||
- Save after 900 seconds if at least 1 key changed
|
||||
- Save after 300 seconds if at least 10 keys changed
|
||||
- Save after 60 seconds if at least 10000 keys changed
|
||||
@@ -293,6 +307,7 @@ When `valkey_maxmemory` is reached, Valkey will behave based on `valkey_maxmemor
|
||||
|
||||
**Important for Immich and BullMQ:**
|
||||
Services using BullMQ for job queues (like Immich) require `noeviction` policy. Evicting job queue data can cause:
|
||||
|
||||
- Lost background tasks
|
||||
- Failed job processing
|
||||
- Data corruption
|
||||
@@ -302,6 +317,7 @@ Only use eviction policies (`allkeys-lru`, etc.) for pure caching use cases wher
|
||||
## Monitoring
|
||||
|
||||
Check Valkey info (authenticate as admin):
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
AUTH default <valkey_admin_password>
|
||||
@@ -311,6 +327,7 @@ INFO stats
|
||||
```
|
||||
|
||||
Check connected clients:
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
AUTH default <valkey_admin_password>
|
||||
@@ -318,6 +335,7 @@ CLIENT LIST
|
||||
```
|
||||
|
||||
View ACL configuration:
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
AUTH default <valkey_admin_password>
|
||||
@@ -328,6 +346,7 @@ ACL CAT # List all command categories
|
||||
```
|
||||
|
||||
Check generated ACL file:
|
||||
|
||||
```bash
|
||||
cat /etc/valkey/users.acl
|
||||
# Example output:
|
||||
@@ -339,12 +358,14 @@ cat /etc/valkey/users.acl
|
||||
## Troubleshooting
|
||||
|
||||
### Check if Valkey is running
|
||||
|
||||
```bash
|
||||
systemctl status valkey # Arch Linux
|
||||
systemctl status valkey-server # Debian/Ubuntu
|
||||
```
|
||||
|
||||
### Test admin connection
|
||||
|
||||
```bash
|
||||
# With authentication (default user)
|
||||
redis-cli
|
||||
@@ -354,6 +375,7 @@ PING
|
||||
```
|
||||
|
||||
### Test service user connection
|
||||
|
||||
```bash
|
||||
# Test Immich user
|
||||
redis-cli
|
||||
@@ -368,6 +390,7 @@ FLUSHDB
|
||||
```
|
||||
|
||||
### View ACL configuration
|
||||
|
||||
```bash
|
||||
# Check ACL file
|
||||
cat /etc/valkey/users.acl
|
||||
@@ -380,6 +403,7 @@ ACL GETUSER immich
|
||||
```
|
||||
|
||||
### Debug permission issues
|
||||
|
||||
```bash
|
||||
# Monitor all commands (useful for debugging)
|
||||
redis-cli
|
||||
@@ -390,6 +414,7 @@ MONITOR
|
||||
```
|
||||
|
||||
### View configuration
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
AUTH default <valkey_admin_password>
|
||||
@@ -397,6 +422,7 @@ CONFIG GET "*"
|
||||
```
|
||||
|
||||
### Check memory usage
|
||||
|
||||
```bash
|
||||
redis-cli
|
||||
AUTH default <valkey_admin_password>
|
||||
@@ -406,25 +432,30 @@ INFO memory
|
||||
### Common ACL Errors
|
||||
|
||||
**"NOAUTH Authentication required"**
|
||||
|
||||
- Client didn't authenticate
|
||||
- Service needs to set `REDIS_USERNAME` and `REDIS_PASSWORD`
|
||||
|
||||
**"WRONGPASS invalid username-password pair"**
|
||||
|
||||
- Incorrect username or password
|
||||
- Verify ACL user exists: `ACL GETUSER username`
|
||||
- Check password in inventory matches service configuration
|
||||
|
||||
**"NOPERM No permissions to run the 'command' command"**
|
||||
|
||||
- Command not allowed in ACL
|
||||
- Check ACL: `ACL GETUSER username`
|
||||
- Add required command to `commands:` in inventory
|
||||
|
||||
**"NOPERM No permissions to access a key"**
|
||||
|
||||
- Key doesn't match allowed patterns
|
||||
- Check key pattern: `ACL GETUSER username`
|
||||
- Verify service is using correct key prefix
|
||||
|
||||
**"NOPERM No permissions to access a channel"**
|
||||
|
||||
- Pub/sub channel not allowed
|
||||
- Add `&*` or `+allchannels` to ACL commands
|
||||
- Required for BullMQ and other job queues
|
||||
@@ -434,18 +465,20 @@ INFO memory
|
||||
For high-traffic services, consider:
|
||||
|
||||
```yaml
|
||||
valkey_maxmemory: 1gb # Increase memory limit
|
||||
valkey_maxmemory_policy: noeviction # No eviction (for job queues)
|
||||
valkey_maxmemory: 1gb # Increase memory limit
|
||||
valkey_maxmemory_policy: noeviction # No eviction (for job queues)
|
||||
# Or for pure caching:
|
||||
# valkey_maxmemory_policy: allkeys-lru # LRU eviction
|
||||
```
|
||||
|
||||
**Kernel Tuning (automatically configured):**
|
||||
The role automatically sets optimal kernel parameters:
|
||||
|
||||
- Memory overcommit enabled (`vm.overcommit_memory=1`)
|
||||
- Transparent Huge Pages set to `madvise`
|
||||
|
||||
To verify kernel settings:
|
||||
|
||||
```bash
|
||||
# Check memory overcommit
|
||||
sysctl vm.overcommit_memory
|
||||
@@ -469,23 +502,27 @@ Created for managing shared Valkey instances in NAS/homelab environments.
|
||||
This role implements **defense-in-depth** with three isolation layers:
|
||||
|
||||
### 1. ACL Users (Primary Isolation)
|
||||
|
||||
Each service gets its own user with restricted permissions:
|
||||
|
||||
- Unique credentials
|
||||
- Key pattern restrictions
|
||||
- Command restrictions
|
||||
|
||||
### 2. Database Numbers (Secondary Isolation)
|
||||
|
||||
Valkey provides 16 logical databases (0-15) for additional isolation:
|
||||
|
||||
| Service | Database | Key Pattern | ACL User |
|
||||
|---------|----------|-------------|----------|
|
||||
| Immich | 0 | `immich_bull*` `immich_channel*` | `immich` |
|
||||
| Nextcloud | 1 | `nextcloud*` | `nextcloud` |
|
||||
| Gitea | 2 | `gitea*` | `gitea` |
|
||||
| Grafana | 3 | `grafana*` | `grafana` |
|
||||
| Custom | 4-15 | Custom | Custom |
|
||||
| Service | Database | Key Pattern | ACL User |
|
||||
| --------- | -------- | -------------------------------- | ----------- |
|
||||
| Immich | 0 | `immich_bull*` `immich_channel*` | `immich` |
|
||||
| Nextcloud | 1 | `nextcloud*` | `nextcloud` |
|
||||
| Gitea | 2 | `gitea*` | `gitea` |
|
||||
| Grafana | 3 | `grafana*` | `grafana` |
|
||||
| Custom | 4-15 | Custom | Custom |
|
||||
|
||||
### 3. Key Prefixes (Tertiary Isolation)
|
||||
|
||||
Services use unique key prefixes enforced by ACL patterns.
|
||||
|
||||
### Testing Isolation
|
||||
@@ -517,23 +554,23 @@ FLUSHDB
|
||||
valkey_admin_password: "{{ vault_valkey_admin_password }}"
|
||||
|
||||
valkey_acl_users:
|
||||
# Immich - Photo management (needs BullMQ job queue)
|
||||
- username: immich
|
||||
password: "{{ vault_immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
|
||||
# Nextcloud - Simple caching
|
||||
- username: nextcloud
|
||||
password: "{{ vault_nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
|
||||
# Gitea - Session store
|
||||
- username: gitea
|
||||
password: "{{ vault_gitea_valkey_password }}"
|
||||
keypattern: "gitea*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
# Immich - Photo management (needs BullMQ job queue)
|
||||
- username: immich
|
||||
password: "{{ vault_immich_valkey_password }}"
|
||||
keypattern: "immich_bull* immich_channel*"
|
||||
commands: "&* -@dangerous +@read +@write +@pubsub +select +auth +ping +info +eval +evalsha"
|
||||
|
||||
# Nextcloud - Simple caching
|
||||
- username: nextcloud
|
||||
password: "{{ vault_nextcloud_valkey_password }}"
|
||||
keypattern: "nextcloud*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
|
||||
# Gitea - Session store
|
||||
- username: gitea
|
||||
password: "{{ vault_gitea_valkey_password }}"
|
||||
keypattern: "gitea*"
|
||||
commands: "+@read +@write -@dangerous +auth +ping +info +select"
|
||||
|
||||
# Service variables
|
||||
immich_valkey_db: 0
|
||||
|
||||
Reference in New Issue
Block a user