Skip to content
Open
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
81 changes: 81 additions & 0 deletions net/owsync/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# SPDX-License-Identifier: MIT

include $(TOPDIR)/rules.mk

PKG_NAME:=owsync
PKG_VERSION:=1.3.0
PKG_RELEASE:=1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/pgaufillet/owsync/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=3b92017e112ac8f1a45584b661757d6ec8f20d56ca7b0d9859d703de02ecac0e

PKG_MAINTAINER:=Pierre Gaufillet <pierre.gaufillet@bergamote.eu>
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE

PKG_BUILD_PARALLEL:=1

include $(INCLUDE_DIR)/package.mk

define Package/owsync
SECTION:=net
CATEGORY:=Network
SUBMENU:=File Transfer
TITLE:=Lightweight bidirectional file synchronization daemon
URL:=https://github.com/pgaufillet/owsync
DEPENDS:=+libjson-c +OWSYNC_ENABLE_ENCRYPTION:libopenssl +rpcd
endef

define Package/owsync/description
owsync is a lightweight, secure, and robust high-availability file
synchronization tool designed specifically for OpenWrt routers.
It provides bi-directional, multi-master synchronization of
configuration files between redundant nodes.
endef

define Package/owsync/config
config OWSYNC_ENABLE_ENCRYPTION
bool "Enable encryption support (AES-256-GCM)"
default y
help
Build owsync with encryption support using OpenSSL.
If disabled, owsync can only be used in plain mode over
secure VPN connections (WireGuard/IPsec).
endef

MAKE_FLAGS += \
PKGCONFIG="$(PKG_CONFIG)" \
ENABLE_ENCRYPTION=$(if $(CONFIG_OWSYNC_ENABLE_ENCRYPTION),1,0)

define Package/owsync/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/owsync $(1)/usr/bin/

$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/owsync.config $(1)/etc/config/owsync

$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/owsync.init $(1)/etc/init.d/owsync

$(INSTALL_DIR) $(1)/etc/owsync

$(INSTALL_DIR) $(1)/usr/libexec/rpcd
$(INSTALL_BIN) ./files/owsync.rpcd $(1)/usr/libexec/rpcd/owsync
endef

define Package/owsync/conffiles
/etc/config/owsync
/etc/owsync/
endef

define Package/owsync/prerm
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
/etc/init.d/owsync stop >/dev/null 2>&1
/etc/init.d/owsync disable >/dev/null 2>&1
fi
exit 0
endef

$(eval $(call BuildPackage,owsync))
26 changes: 26 additions & 0 deletions net/owsync/files/owsync.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
config owsync 'general'
option enabled '0'
option host '::'
option port '4321'
option dir '/etc/config'
option db '/etc/owsync/owsync.db'
option key 'GENERATE_WITH_OWSYNC_GENKEY'
option poll_interval '60'

# Plain mode (no encryption) - only use over secure VPN
# option plain_mode '1'

# Target Peers for automatic sync
# List peer hostnames/IPs (all use the same port)
# list peer '192.168.1.2'
# list peer 'fd00::2'

# Whitelist specific files (required - if empty, nothing is synced)
# Use 'list include *' to sync all files
# list include 'firewall'
# list include 'dhcp'

# Blacklist specific files (takes precedence over includes)
list exclude 'network'
list exclude 'system'
list exclude 'owsync'
143 changes: 143 additions & 0 deletions net/owsync/files/owsync.init
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/bin/sh /etc/rc.common
# SPDX-License-Identifier: MIT
# Copyright (c) 2025-2026 Pierre Gaufillet <pierre.gaufillet@bergamote.eu>

START=99
STOP=10
USE_PROCD=1

# Dependencies: network must be up before owsync can bind/connect
DEPEND="network"

CONF_FILE="/tmp/owsync.conf"

# Collect list items into shell variables
PEERS=""
INCLUDES=""
EXCLUDES=""

append_peer() {
PEERS="$PEERS $1"
}

append_include() {
INCLUDES="$INCLUDES $1"
}

append_exclude() {
EXCLUDES="$EXCLUDES $1"
}

generate_config() {
local host="$1"
local port="$2"
local key="$3"
local dir="$4"
local db="$5"
local poll_interval="$6"
local plain_mode="$7"

# Create config file with restricted permissions (key inside)
rm -f "$CONF_FILE"
touch "$CONF_FILE"
chmod 600 "$CONF_FILE"

cat > "$CONF_FILE" <<EOF
# Auto-generated by owsync init script
# Do not edit - changes will be overwritten on restart

bind_host=$host
port=$port
sync_dir=$dir
database=$db
poll_interval=$poll_interval
log_level=2
EOF

# Add encryption key or plain mode
if [ "$plain_mode" = "1" ]; then
echo "plain_mode=1" >> "$CONF_FILE"
else
echo "encryption_key=$key" >> "$CONF_FILE"
fi

# Add peers
for peer in $PEERS; do
echo "peer=$peer" >> "$CONF_FILE"
done

# Add includes
for inc in $INCLUDES; do
echo "include=$inc" >> "$CONF_FILE"
done

# Add excludes
for exc in $EXCLUDES; do
echo "exclude=$exc" >> "$CONF_FILE"
done
}

start_service() {
config_load owsync

local enabled
config_get_bool enabled general enabled 0
[ "$enabled" -eq 1 ] || return 0

local host port key dir db poll_interval plain_mode
config_get host general host "::"
config_get port general port "4321"
config_get key general key
config_get dir general dir "/etc/config"
config_get db general db "/etc/owsync/owsync.db"
config_get poll_interval general poll_interval "60"
config_get_bool plain_mode general plain_mode 0

# Collect list items
PEERS=""
INCLUDES=""
EXCLUDES=""
config_list_foreach "general" "peer" append_peer
config_list_foreach "general" "include" append_include
config_list_foreach "general" "exclude" append_exclude

# Validate key (unless plain mode)
if [ "$plain_mode" != "1" ]; then
if [ -z "$key" ] || [ "$key" = "GENERATE_WITH_OWSYNC_GENKEY" ]; then
logger -t owsync -p daemon.err "Error: owsync key not configured"
return 1
fi
fi

# Validate peers for daemon mode
if [ -z "$PEERS" ]; then
logger -t owsync -p daemon.err "Error: owsync requires at least one peer for daemon mode"
return 1
fi

# Ensure DB directory exists
local db_dir
db_dir=$(dirname "$db")
[ -d "$db_dir" ] || mkdir -p "$db_dir"

# Generate config file (key stays in file, not command line)
generate_config "$host" "$port" "$key" "$dir" "$db" "$poll_interval" "$plain_mode"

# Start daemon with config file
procd_open_instance "owsync"
procd_set_param command /usr/bin/owsync daemon -c "$CONF_FILE"
procd_set_param respawn
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param file /etc/config/owsync
procd_close_instance
}

stop_service() {
# Clean up generated config file
rm -f "$CONF_FILE"
}

service_triggers() {
procd_add_reload_trigger "owsync"
}
Loading