On NetBSD, the SQLite Backup and Close methods used by renterd and hostd (Sia decentralized data storage) depend on CGO-specific features of the go-sqlite3 driver, which are not fully supported on this platform.
Attempts to substitute go-sqlite3 with CGO-free alternatives such as modernc.org/sqlite or ncruces/go-sqlite3 proved impractical due to required structural changes in the codebase, despite preliminary efforts.
Consequently, Backup and Close functionalities have been disabled in this howto to allow successful compilation and runtime on NetBSD 10.1.
Regular manual backups should be performed using standard SQLite commands, e.g., sqlite3 db.sqlite \".backup 'db.bkp'\".
Prerequisites
- Complete NetBSD version or without X11 (minimal version is insufficient due to missing header files).
Install necessary packages
pkgin update
pkgin -y install go124 git gcc14 tmux
Clone the repository
cd /tmp
git clone https://github.com/SiaFoundation/renterd.git
cd renterd
SQLite Installation (CGO)
go124 install github.com/mattn/go-sqlite3
Required modifications to the source code
- Disable the backupDB function in renterd:
Edit /tmp/renterd/stores/sql/sqlite/backup.go, replace the entire backupDB function (starting from line 36) :
func backupDB(ctx context.Context, src *dsql.DB, destPath string) (err error) {
// create the destination database
dest, err := dsql.Open("sqlite3", destPath)
if err != nil {
return fmt.Errorf("failed to open destination database: %w", err)
}
defer func() {
// errors are ignored
dest.Close()
if err != nil {
// remove the destination file if an error occurred during backup
os.Remove(destPath)
}
}()
// initialize the source conn
sc, err := sqlConn(ctx, src)
if err != nil {
return fmt.Errorf("failed to create source connection: %w", err)
}
defer sc.Close()
// initialize the destination conn
dc, err := sqlConn(ctx, dest)
if err != nil {
return fmt.Errorf("failed to create destination connection: %w", err)
}
defer dc.Close()
// start the backup
// NOTE: 'main' referes to the schema of the database
backup, err := dc.Backup("main", sc, "main")
if err != nil {
return fmt.Errorf("failed to create backup: %w", err)
}
// ensure the backup is closed
defer func() {
if err := backup.Finish(); err != nil {
panic(fmt.Errorf("failed to finish backup: %w", err))
}
}()
for step := 1; ; step++ {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if done, err := backup.Step(100); err != nil {
return fmt.Errorf("backup step %d failed: %w", step, err)
} else if done {
break
}
}
if _, err := dest.Exec("VACUUM"); err != nil {
return fmt.Errorf("failed to vacuum destination database: %w", err)
}
return nil
}
with:
func backupDB(ctx context.Context, src *dsql.DB, destPath string) (err error) {
// deactivation for NetBSD
return nil
}
- Apply modifications to hostd:
Enable editing:
chmod +w /root/go/pkg/mod/go.sia.tech/hostd/v2@v2.2.3/persist/sqlite/store.go
Edit this file and replace the entire backupDB function :
func backupDB(ctx context.Context, src *sql.DB, destPath string) (err error) {
// create the destination database
dest, err := sql.Open("sqlite3", sqliteFilepath(destPath))
if err != nil {
return fmt.Errorf("failed to open destination database: %w", err)
}
defer func() {
// errors are ignored
dest.Close()
if err != nil {
// remove the destination file if an error occurred during backup
os.Remove(destPath)
}
}()
// initialize the source conn
sc, err := sqlConn(ctx, src)
if err != nil {
return fmt.Errorf("failed to create source connection: %w", err)
}
defer sc.Close()
// initialize the destination conn
dc, err := sqlConn(ctx, dest)
if err != nil {
return fmt.Errorf("failed to create destination connection: %w", err)
}
defer dc.Close()
// start the backup
backup, err := dc.Backup("main", sc, "main")
if err != nil {
return fmt.Errorf("failed to create backup: %w", err)
}
// ensure the backup is closed
defer func() {
if err := backup.Finish(); err != nil {
panic(fmt.Errorf("failed to finish backup: %w", err))
}
}()
for step := 1; ; step++ {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if done, err := backup.Step(100); err != nil {
return fmt.Errorf("backup step %d failed: %w", step, err)
} else if done {
break
}
}
if _, err := dest.Exec("VACUUM"); err != nil {
return fmt.Errorf("failed to vacuum destination database: %w", err)
}
return nil
}
with:
func backupDB(ctx context.Context, src *sql.DB, destPath string) (err error) {
// deactivation for NetBSD
return nil
}
Also, replace the line:
sqliteVersion, _, _ := sqlite3.Version()
with:
sqliteVersion := "deactivated"
Compilation
cd /tmp/renterd
export CGO_ENABLED=1
go124 mod tidy
go124 build -v ./...
cd cmd/renterd
go124 build
Binary installation
mkdir -p /opt/renterd/bin
mv /tmp/renterd/* /opt/renterd/
cp /opt/renterd/cmd/renterd/renterd /opt/renterd/bin/
Creating a dedicated secure user
groupadd renterd
useradd -g renterd -d /var/empty -s /sbin/nologin -c "renterd Daemon" renterd
Applying strict permissions
chown -R renterd:renterd /opt/renterd
chmod -R 750 /opt/renterd
Starting renterd with tmux (simple example)
tmux new -s renterd
usermod -s /bin/sh renterd
su renterd -c 'cd /opt/renterd && /opt/renterd/bin/renterd'
On first launch, initialize with the corresponding seed phrase and wallet address.
Detach the tmux session: Ctrl+b, then d
Remove the interactive shell from the user:
usermod -s /bin/false renterd
Off course, create a service and a /opt/renterd/renterd.yml configuration file.
In order to access the web console of renterd, just create an SSH tunnel (-L9980 127.0.0.1:9980) between your client and the server, and use your browser (http://127.0.0.1:9980
)