prepare: configures snapcast server and client
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Marvin Steadfast 2021-04-29 13:41:37 +02:00
parent 979040227e
commit 9af55ee991
3 changed files with 156 additions and 48 deletions

View File

@ -1,10 +1,12 @@
proc /proc proc defaults 0 0 proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat ro,defaults 0 2 /dev/mmcblk0p1 /boot vfat ro,defaults 0 2
/dev/mmcblk0p2 / ext4 ro,defaults,noatime 0 1 /dev/mmcblk0p2 / ext4 ro,defaults,noatime 0 1
tmpfs /var/log tmpfs nodev,nosuid 0 0 tmpfs /var/log tmpfs nodev,nosuid 0 0
tmpfs /var/tmp tmpfs nodev,nosuid 0 0 tmpfs /var/tmp tmpfs nodev,nosuid 0 0
tmpfs /tmp tmpfs nodev,nosuid 0 0 tmpfs /tmp tmpfs nodev,nosuid 0 0
tmpfs /var/lib/systemd/timesync tmpfs auto,noatime,size=5m,mode=0755,uid={{.TimesyncUID}},gid={{.TimesyncGID}} 0 0 tmpfs /var/lib/systemd/timesync tmpfs auto,noatime,size=5m,mode=0755,uid={{.TimesyncUID}},gid={{.TimesyncGID}} 0 0
tmpfs /var/cache/mopidy tmpfs auto,noatime,size=5m,mode=0755,uid={{.MopidyUID}},gid={{.MopidyGID}} 0 0 tmpfs /var/cache/mopidy tmpfs auto,noatime,size=5m,mode=0755,uid={{.MopidyUID}},gid={{.MopidyGID}} 0 0
tmpfs /var/cache/upmpdcli tmpfs auto,noatime,size=5m,mode=0755,uid={{.UpmpdcliUID}},gid={{.UpmpdcliGID}} 0 0 tmpfs /var/cache/upmpdcli tmpfs auto,noatime,size=5m,mode=0755,uid={{.UpmpdcliUID}},gid={{.UpmpdcliGID}} 0 0
tmpfs /var/lib/ntp tmpfs nosuid,nodev 0 0 tmpfs /var/lib/ntp tmpfs nosuid,nodev 0 0
tmpfs /var/lib/snapserver tmpfs nosuid,nodev 0 0
tmpfs /var/lib/snapclient tmpfs nosuid,nodev 0 0

View File

@ -3,7 +3,7 @@ cache_dir = /var/cache/mopidy
config_dir = /etc/mopidy/ config_dir = /etc/mopidy/
[audio] [audio]
output = alsasink output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format=S16LE ! filesink location=/tmp/snapfifo
mixer = alsamixer mixer = alsamixer
mixer_volume = 100 mixer_volume = 100
@ -11,7 +11,6 @@ mixer_volume = 100
card = 0 card = 0
control= Headphone control= Headphone
[mpd] [mpd]
hostname = 0.0.0.0 hostname = 0.0.0.0

View File

@ -27,6 +27,10 @@ const (
schnutboxConfigDir = "/etc/schnutibox" schnutboxConfigDir = "/etc/schnutibox"
upmpdcliUser = "upmpdcli" upmpdcliUser = "upmpdcli"
upmpdcliGroup = "nogroup" upmpdcliGroup = "nogroup"
snapserverUser = "snapserver"
snapserverGroup = "snapserver"
snapclientUser = "snapclient"
snapclientGroup = "snapclient"
) )
var Cfg = struct { var Cfg = struct {
@ -41,11 +45,11 @@ var Cfg = struct {
System string System string
}{} }{}
// BoxService creates a systemd service for schnutibox. // boxService creates a systemd service for schnutibox.
func BoxService(filename string, enable bool) error { func boxService(filename string, enable bool) error {
logger := log.With().Str("stage", "BoxService").Logger() logger := log.With().Str("stage", "BoxService").Logger()
if err := CreateUser(); err != nil { if err := createUser(); err != nil {
return fmt.Errorf("could not create user: %w", err) return fmt.Errorf("could not create user: %w", err)
} }
@ -83,7 +87,7 @@ func BoxService(filename string, enable bool) error {
return nil return nil
} }
func NTP() error { func ntp() error {
logger := log.With().Str("stage", "NTP").Logger() logger := log.With().Str("stage", "NTP").Logger()
cmd := exec.Command("apt-get", "install", "-y", "ntp", "ntpdate") cmd := exec.Command("apt-get", "install", "-y", "ntp", "ntpdate")
@ -119,9 +123,9 @@ func NTP() error {
return nil return nil
} }
// Fstab creates a fstab for a read-only system. // fstab creates a fstab for a read-only system.
// nolint:funlen // nolint:funlen
func Fstab(system string) error { func fstab(system string) error {
logger := log.With().Str("stage", "Fstab").Logger() logger := log.With().Str("stage", "Fstab").Logger()
// Getting timesync user and group informations. // Getting timesync user and group informations.
@ -163,6 +167,31 @@ func Fstab(system string) error {
logger.Debug().Str("uid", upmpdcliUser.Uid).Str("gid", upmpdcliGroup.Gid).Msg("upmpdcli") logger.Debug().Str("uid", upmpdcliUser.Uid).Str("gid", upmpdcliGroup.Gid).Msg("upmpdcli")
// Getting snapserver user and group informations.
snapserverUser, err := user.Lookup(snapserverUser)
if err != nil {
return fmt.Errorf("could not lookup snapserver user: %w", err)
}
snapserverGroup, err := user.LookupGroup(snapserverGroup)
if err != nil {
return fmt.Errorf("could not lookup snapserver group: %w", err)
}
logger.Debug().Str("uid", snapserverUser.Uid).Str("gid", snapserverGroup.Gid).Msg("snapserver")
snapclientUser, err := user.Lookup(snapclientUser)
if err != nil {
return fmt.Errorf("could not lookup snapclient user: %w", err)
}
snapclientGroup, err := user.LookupGroup(snapclientGroup)
if err != nil {
return fmt.Errorf("could not lookup snapclient group: %w", err)
}
logger.Debug().Str("uid", snapclientUser.Uid).Str("gid", snapclientGroup.Gid).Msg("snapclient")
// Chose the right template. // Chose the right template.
// In future it should be a switch statement. // In future it should be a switch statement.
tmpl, err := assets.Assets.ReadFile("templates/fstab.raspbian.tmpl") tmpl, err := assets.Assets.ReadFile("templates/fstab.raspbian.tmpl")
@ -182,12 +211,16 @@ func Fstab(system string) error {
// Create and write. // Create and write.
if err := t.Execute(f, struct { if err := t.Execute(f, struct {
TimesyncUID string TimesyncUID string
TimesyncGID string TimesyncGID string
MopidyUID string MopidyUID string
MopidyGID string MopidyGID string
UpmpdcliUID string UpmpdcliUID string
UpmpdcliGID string UpmpdcliGID string
SnapserverUID string
SnapserverGID string
SnapclientUID string
SnapclientGID string
}{ }{
timesyncUser.Uid, timesyncUser.Uid,
timesyncGroup.Gid, timesyncGroup.Gid,
@ -195,6 +228,10 @@ func Fstab(system string) error {
mopidyGroup.Gid, mopidyGroup.Gid,
upmpdcliUser.Uid, upmpdcliUser.Uid,
upmpdcliGroup.Gid, upmpdcliGroup.Gid,
snapserverUser.Uid,
snapserverGroup.Gid,
snapclientUser.Uid,
snapclientGroup.Gid,
}); err != nil { }); err != nil {
return fmt.Errorf("could not write templated fstab: %w", err) return fmt.Errorf("could not write templated fstab: %w", err)
} }
@ -202,8 +239,8 @@ func Fstab(system string) error {
return nil return nil
} }
// RemovePkgs removes not needed software in read-only mode. // removePkgs removes not needed software in read-only mode.
func RemovePkgs(system string) error { func removePkgs(system string) error {
logger := log.With().Str("stage", "RemovePkgs").Logger() logger := log.With().Str("stage", "RemovePkgs").Logger()
if system != "raspbian" { if system != "raspbian" {
logger.Info().Msg("nothing to do") logger.Info().Msg("nothing to do")
@ -240,7 +277,7 @@ func RemovePkgs(system string) error {
return nil return nil
} }
func CreateUDEVrules() error { func udevRules() error {
logger := log.With().Str("stage", "CreateUDEVrules").Logger() logger := log.With().Str("stage", "CreateUDEVrules").Logger()
logger.Info().Msg("writing udev rule file") logger.Info().Msg("writing udev rule file")
@ -271,8 +308,8 @@ func CreateUDEVrules() error {
return nil return nil
} }
// CreateUser creates schnutibox system user and group. // createUser creates schnutibox system user and group.
func CreateUser() error { func createUser() error {
logger := log.With().Str("stage", "CreateUser").Logger() logger := log.With().Str("stage", "CreateUser").Logger()
cmd := exec.Command("adduser", "--system", "--group", "--no-create-home", schnutiboxUser) cmd := exec.Command("adduser", "--system", "--group", "--no-create-home", schnutiboxUser)
@ -285,8 +322,8 @@ func CreateUser() error {
return nil return nil
} }
// CreateSymlinks creates all needed symlinks. // symlinks creates all needed symlinks.
func CreateSymlinks(system string) error { func symlinks(system string) error {
logger := log.With().Str("stage", "Symlinks").Logger() logger := log.With().Str("stage", "Symlinks").Logger()
links := []struct { links := []struct {
@ -365,17 +402,17 @@ func cmdlineTxt() error {
return nil return nil
} }
// makeReadOnly executes stuff if a read-only system is wanted. // readOnly executes stuff if a read-only system is wanted.
func makeReadOnly(system string) error { func readOnly(system string) error {
if err := RemovePkgs(system); err != nil { if err := removePkgs(system); err != nil {
return fmt.Errorf("could not remove pkgs: %w", err) return fmt.Errorf("could not remove pkgs: %w", err)
} }
if err := CreateSymlinks(system); err != nil { if err := symlinks(system); err != nil {
return fmt.Errorf("could not create symlinks: %w", err) return fmt.Errorf("could not create symlinks: %w", err)
} }
if err := Fstab(system); err != nil { if err := fstab(system); err != nil {
return fmt.Errorf("could not create fstab: %w", err) return fmt.Errorf("could not create fstab: %w", err)
} }
@ -386,9 +423,9 @@ func makeReadOnly(system string) error {
return nil return nil
} }
// Mopidy setups mopidy. // mopidy setups mopidy.
//nolint:funlen,cyclop //nolint:funlen,cyclop
func Mopidy() error { func mopidy() error {
logger := log.With().Str("stage", "Mopidy").Logger() logger := log.With().Str("stage", "Mopidy").Logger()
// GPG Key. // GPG Key.
@ -501,7 +538,7 @@ func Mopidy() error {
// Upmpdcli setups upmpdcli. // Upmpdcli setups upmpdcli.
//nolint:funlen //nolint:funlen
func Upmpdcli() error { func upmpdcli() error {
logger := log.With().Str("stage", "Upmpdcli").Logger() logger := log.With().Str("stage", "Upmpdcli").Logger()
// GPG Key. // GPG Key.
@ -584,8 +621,73 @@ func Upmpdcli() error {
return nil return nil
} }
func SchnutiboxConfig() error { // nolint:funlen
logger := log.With().Str("stage", "Upmpdcli").Logger() func snapcast() error {
logger := log.With().Str("stage", "snapcast").Logger()
// Download deb.
cmd := exec.Command(
"wget",
"https://github.com/badaix/snapcast/releases/download/v0.24.0/snapclient_0.24.0-1_without-pulse_armhf.deb",
"-O", "/tmp/snapclient.deb",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logger.Debug().Str("cmd", cmd.String()).Msg("running")
if err := cmd.Run(); err != nil {
return fmt.Errorf("could not download snapclient deb: %w", err)
}
// Install deb
cmd = exec.Command(
"/bin/sh", "-c",
"dpkg -i /tmp/snapclient.deb; apt --fix-broken install -y; rm /tmp/snapclient.deb",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logger.Debug().Str("cmd", cmd.String()).Msg("running")
if err := cmd.Run(); err != nil {
return fmt.Errorf("could not install snapclient deb: %w", err)
}
// Download deb.
cmd = exec.Command(
"wget",
"https://github.com/badaix/snapcast/releases/download/v0.24.0/snapserver_0.24.0-1_armhf.deb",
"-O", "/tmp/snapserver.deb",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logger.Debug().Str("cmd", cmd.String()).Msg("running")
if err := cmd.Run(); err != nil {
return fmt.Errorf("could not download snapserver deb: %w", err)
}
// Install deb
cmd = exec.Command(
"/bin/sh", "-c",
"dpkg -i /tmp/snapserver.deb; apt --fix-broken install -y; rm /tmp/snapserver.deb",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logger.Debug().Str("cmd", cmd.String()).Msg("running")
if err := cmd.Run(); err != nil {
return fmt.Errorf("could not install snapserver deb: %w", err)
}
return nil
}
func schnutiboxConfig() error {
logger := log.With().Str("stage", "schnutiboxConfig").Logger()
logger.Info().Msg("writing schnutibox config") logger.Info().Msg("writing schnutibox config")
// Parse template. // Parse template.
@ -615,38 +717,43 @@ func Run(cmd *cobra.Command, args []string) {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
// Install schnutibox service. // Install schnutibox service.
if err := BoxService(serviceLocation+"/"+serviceFileName, true); err != nil { if err := boxService(serviceLocation+"/"+serviceFileName, true); err != nil {
log.Fatal().Err(err).Msg("could not create schnutibox service") log.Fatal().Err(err).Msg("could not create schnutibox service")
} }
// Create schnutibox config. // Create schnutibox config.
if err := SchnutiboxConfig(); err != nil { if err := schnutiboxConfig(); err != nil {
log.Fatal().Err(err).Msg("could not create schnutibox config.") log.Fatal().Err(err).Msg("could not create schnutibox config.")
} }
// Install udev file. // Install udev file.
if err := CreateUDEVrules(); err != nil { if err := udevRules(); err != nil {
log.Fatal().Err(err).Msg("could not install udev rules") log.Fatal().Err(err).Msg("could not install udev rules")
} }
// Setup NTP. // Setup NTP.
if err := NTP(); err != nil { if err := ntp(); err != nil {
log.Fatal().Err(err).Msg("could not setup ntp") log.Fatal().Err(err).Msg("could not setup ntp")
} }
// Setup mopidy. // Setup mopidy.
if err := Mopidy(); err != nil { if err := mopidy(); err != nil {
log.Fatal().Err(err).Msg("could not setup mopidy") log.Fatal().Err(err).Msg("could not setup mopidy")
} }
// Setup upmpdcli. // Setup upmpdcli.
if err := Upmpdcli(); err != nil { if err := upmpdcli(); err != nil {
log.Fatal().Err(err).Msg("could not setup upmpdcli") log.Fatal().Err(err).Msg("could not setup upmpdcli")
} }
// Setup snapcast.
if err := snapcast(); err != nil {
log.Fatal().Err(err).Msg("could not setup snapclient")
}
// Making system read-only. // Making system read-only.
if Cfg.ReadOnly { if Cfg.ReadOnly {
if err := makeReadOnly(Cfg.System); err != nil { if err := readOnly(Cfg.System); err != nil {
log.Fatal().Err(err).Msg("could not make system read-only") log.Fatal().Err(err).Msg("could not make system read-only")
} }
} }