Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ readonly ST_USER_2="bob"
# Service names (constructed automatically)
readonly ST_SERVICE_1="syncthing@${ST_USER_1}.service"
readonly ST_SERVICE_2="syncthing@${ST_USER_2}.service"

# Additional services (set to "none" to disable)
readonly DOCKER_SERVICE="docker.service" # Manage Docker service
readonly SAMBA_SERVICE="smbd.service" # Manage Samba service (for network shares)
```

All configured services are started when running `srv-ctl.sh start` and stopped when running `srv-ctl.sh stop`.

### Storage Device Configuration

Each storage device supports:
Expand Down
1 change: 1 addition & 0 deletions config.local.template
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ readonly ST_USER_2="none" # Set to username to enable (e.g., "bob")
readonly ST_SERVICE_1=$([ "$ST_USER_1" != "none" ] && echo "syncthing@${ST_USER_1}.service" || echo "none")
readonly ST_SERVICE_2=$([ "$ST_USER_2" != "none" ] && echo "syncthing@${ST_USER_2}.service" || echo "none")
readonly DOCKER_SERVICE="none" # Set to "docker.service" to enable
readonly SAMBA_SERVICE="none" # Set to "smbd.service" to enable (for network shares)

# -----------------------------------------------------------------------------
# Primary data device configuration
Expand Down
8 changes: 5 additions & 3 deletions srv-ctl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#
# DESCRIPTION:
# Manages encrypted storage devices, LVM volumes, and services for a multi-user
# Syncthing setup with support for LUKS/BitLocker encryption and network shares.
# setup with support for LUKS/BitLocker encryption and network shares.
#
# FEATURES:
# - Supports 2 parallel Syncthing services with separate users
# - Supports multiple systemd services (Syncthing, Docker, Samba, etc.)
# - Manages 5 storage devices (1 primary data + 4 paired storage devices)
# - LUKS and BitLocker encryption support via cryptsetup 2.4.0+
# - Optional LVM integration per device
Expand Down Expand Up @@ -200,7 +200,7 @@ function close_all_devices() {
# -----------------------------------------------------------------------------

function start_all_services() {
if [ "$ST_SERVICE_1" != "none" ] || [ "$ST_SERVICE_2" != "none" ] || [ "$DOCKER_SERVICE" != "none" ]; then
if [ "$ST_SERVICE_1" != "none" ] || [ "$ST_SERVICE_2" != "none" ] || [ "$DOCKER_SERVICE" != "none" ] || [ "$SAMBA_SERVICE" != "none" ]; then
echo "Reloading systemd units..."
if ! systemctl daemon-reload; then
echo "ERROR: Failed to reload systemd units"
Expand All @@ -215,12 +215,14 @@ function start_all_services() {
start_service "$ST_SERVICE_1" || return "$FAILURE"
start_service "$ST_SERVICE_2" || return "$FAILURE"
start_service "$DOCKER_SERVICE" || return "$FAILURE"
start_service "$SAMBA_SERVICE" || return "$FAILURE"
}

function stop_all_services() {
stop_service "$ST_SERVICE_1"
stop_service "$ST_SERVICE_2"
stop_service "$DOCKER_SERVICE"
stop_service "$SAMBA_SERVICE"
}

# -----------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ Integration tests cover real storage operations (LUKS, LVM, mount, network share
- **test-luks-keyfile.bats**: LUKS key file authentication (valid, missing, unreadable, wrong key, symlink, spaces, error handling)
- **test-network-shares.bats**: Network share mounting (CIFS/NFS) with real Samba/NFS servers, credentials, error handling, idempotency, and permission scenarios
- **test-bitlocker.bats**: BitLocker encryption support (unlock/lock with key files, error handling, idempotency, integration with srv-ctl.sh)
- **test-services.bats**: Service management edge cases (start/stop, idempotency, error handling for nonexistent/failing services)
- **test-services.bats**: Service management edge cases (start/stop, idempotency, error handling for nonexistent/failing services, SAMBA_SERVICE integration)

All integration tests are run in CI via VM on all supported OSes.

### System Tests

System tests validate full CLI workflows using srv-ctl.sh, including device orchestration, service management, and network share mounting. These tests use real services and config patching to simulate production scenarios.

- **test-system.sh**: Covers start/stop/unlock workflows, config validation, error handling, multi-device orchestration (PRIMARY + multiple STORAGE + NETWORK_SHARE), and key file authentication tests as part of the main workflow.
- **test-system.sh**: Covers start/stop/unlock workflows, config validation, error handling, multi-device orchestration (PRIMARY + multiple STORAGE + NETWORK_SHARE), service management (including SAMBA_SERVICE with real smbd), and key file authentication tests as part of the main workflow.

All system tests are run in CI via VM on all supported OSes.

Expand Down
1 change: 1 addition & 0 deletions tests/e2e/test-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ readonly ST_SERVICE_1="ssh"
readonly ST_USER_2="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

# Primary Data Device (uses test environment)
readonly PRIMARY_DATA_UUID="$TEST_LOOP_UUID"
Expand Down
1 change: 1 addition & 0 deletions tests/integration/test-bitlocker.bats
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ readonly ST_SERVICE_1="none"
readonly ST_USER_2="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"
readonly PRIMARY_DATA_UUID="$TEST_BITLOCKER_UUID"
readonly PRIMARY_DATA_KEY_FILE="$TEST_BITLOCKER_KEY_FILE"
readonly PRIMARY_DATA_ENCRYPTION_TYPE="bitlocker"
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/test-config-validation.bats
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="/tmp/test_keyfile_is_dir"
Expand Down Expand Up @@ -90,6 +91,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="/tmp/test_unreadable_keyfile"
Expand Down Expand Up @@ -140,6 +142,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="/tmp/test_symlink_keyfile"
Expand Down Expand Up @@ -182,6 +185,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="/tmp/test_broken_symlink"
Expand Down Expand Up @@ -228,6 +232,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -267,6 +272,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-test"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -310,6 +316,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid-1"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -363,6 +370,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="none"

Expand Down
8 changes: 8 additions & 0 deletions tests/integration/test-ownership.bats
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="syncthing@test_user_1.service"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="none"
readonly STORAGE_1A_UUID="none"
Expand Down Expand Up @@ -184,6 +185,7 @@ readonly ST_USER_2="test_user_2"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="syncthing@test_user_2.service"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="none"
readonly STORAGE_1A_UUID="none"
Expand Down Expand Up @@ -222,6 +224,7 @@ readonly ST_USER_2="test_user_2"
readonly ST_SERVICE_1="syncthing@test_user_1.service"
readonly ST_SERVICE_2="syncthing@test_user_2.service"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="none"
readonly STORAGE_1A_UUID="none"
Expand Down Expand Up @@ -261,6 +264,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1=""
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="none"
readonly STORAGE_1A_UUID="none"
Expand Down Expand Up @@ -303,6 +307,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -351,6 +356,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -399,6 +405,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down Expand Up @@ -447,6 +454,7 @@ readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="none"

readonly PRIMARY_DATA_UUID="12345678-fake-uuid"
readonly PRIMARY_DATA_KEY_FILE="none"
Expand Down
56 changes: 56 additions & 0 deletions tests/integration/test-services.bats
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,59 @@ setup() {
run sudo bash -c "source $PROJECT_ROOT/lib/os-utils.sh && stop_service ''"
[ "$status" -ne 0 ]
}

@test "SAMBA_SERVICE integration: Service properly managed when configured" {
# This test verifies that when SAMBA_SERVICE is configured in config.local,
# it's properly included in the start_all_services and stop_all_services workflow

# Backup existing config
[ -f "$PROJECT_ROOT/config.local" ] && cp "$PROJECT_ROOT/config.local" "$PROJECT_ROOT/config.local.test_backup"

# Create minimal config with SAMBA_SERVICE pointing to our test service
cat > "$PROJECT_ROOT/config.local" <<EOF
readonly CRYPTSETUP_MIN_VERSION="2.4.0"
readonly ST_USER_1="none"
readonly ST_USER_2="none"
readonly ST_SERVICE_1="none"
readonly ST_SERVICE_2="none"
readonly DOCKER_SERVICE="none"
readonly SAMBA_SERVICE="test-dummy-service"

readonly PRIMARY_DATA_UUID="none"
readonly STORAGE_1A_UUID="none"
readonly STORAGE_1B_UUID="none"
readonly STORAGE_2A_UUID="none"
readonly STORAGE_2B_UUID="none"

readonly NETWORK_SHARE_PROTOCOL="none"
readonly NETWORK_SHARE_ADDRESS="none"
readonly NETWORK_SHARE_CREDENTIALS="none"
readonly NETWORK_SHARE_MOUNT="none"
readonly NETWORK_SHARE_OWNER_USER="none"
readonly NETWORK_SHARE_OWNER_GROUP="none"
readonly NETWORK_SHARE_OPTIONS="defaults"
EOF

# Ensure test service is stopped
sudo systemctl stop test-dummy-service 2>/dev/null || true

# Call start_service for SAMBA_SERVICE
run sudo bash -c "source $PROJECT_ROOT/config.local && source $PROJECT_ROOT/lib/os-utils.sh && start_service \"\$SAMBA_SERVICE\""
[ "$status" -eq 0 ]

# Verify test service is now running (Samba was started)
run sudo systemctl is-active test-dummy-service
[ "$status" -eq 0 ]

# Call stop_service for SAMBA_SERVICE
run sudo bash -c "source $PROJECT_ROOT/config.local && source $PROJECT_ROOT/lib/os-utils.sh && stop_service \"\$SAMBA_SERVICE\""
[ "$status" -eq 0 ]

# Verify test service is now stopped (Samba was stopped)
run sudo systemctl is-active test-dummy-service
[ "$status" -ne 0 ]

# Restore config
[ -f "$PROJECT_ROOT/config.local.test_backup" ] && mv "$PROJECT_ROOT/config.local.test_backup" "$PROJECT_ROOT/config.local"
rm -f "$PROJECT_ROOT/config.local.test_backup"
}
Loading
Loading