summaryrefslogtreecommitdiff
path: root/modules/profiles
diff options
context:
space:
mode:
Diffstat (limited to 'modules/profiles')
-rw-r--r--modules/profiles/files/firewall/rules.v415
-rwxr-xr-xmodules/profiles/files/passmenu29
-rw-r--r--modules/profiles/files/ssh-agent.service13
-rw-r--r--modules/profiles/lib/facter/pacman_version.rb7
-rw-r--r--modules/profiles/manifests/dolphin.pp70
-rw-r--r--modules/profiles/manifests/firewall.pp19
-rw-r--r--modules/profiles/manifests/gandalf_web.pp102
-rw-r--r--modules/profiles/manifests/group_profile.pp16
-rw-r--r--modules/profiles/manifests/imagemagick.pp17
-rw-r--r--modules/profiles/manifests/remarkable.pp31
-rw-r--r--modules/profiles/manifests/syncthing.pp28
-rw-r--r--modules/profiles/manifests/synth.pp33
-rw-r--r--modules/profiles/manifests/transmission.pp71
-rw-r--r--modules/profiles/manifests/webdav_server.pp80
-rw-r--r--modules/profiles/manifests/workstation.pp132
-rw-r--r--modules/profiles/manifests/workstation/archlinux.pp52
-rw-r--r--modules/profiles/manifests/xmonad.pp29
-rw-r--r--modules/profiles/templates/aconnect.epp8
-rw-r--r--modules/profiles/templates/imagemagick-policy.xml.epp89
-rw-r--r--modules/profiles/templates/keyvalue.epp4
-rw-r--r--modules/profiles/templates/transmission.json.epp77
21 files changed, 922 insertions, 0 deletions
diff --git a/modules/profiles/files/firewall/rules.v4 b/modules/profiles/files/firewall/rules.v4
new file mode 100644
index 0000000..bdc63cc
--- /dev/null
+++ b/modules/profiles/files/firewall/rules.v4
@@ -0,0 +1,15 @@
+# Generated by iptables-save v1.8.4 on Thu Jun 3 20:27:52 2021
+*filter
+:INPUT DROP [120:97784]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [526:114637]
+-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A INPUT -p udp -m udp --dport 67:68 -j ACCEPT
+-A INPUT -p icmp -j ACCEPT
+-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
+-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
+-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
+-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
+-A INPUT -p udp -m udp --dport 53 -j ACCEPT
+COMMIT
+# Completed on Thu Jun 3 20:27:52 2021
diff --git a/modules/profiles/files/passmenu b/modules/profiles/files/passmenu
new file mode 100755
index 0000000..653ebda
--- /dev/null
+++ b/modules/profiles/files/passmenu
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+shopt -s nullglob globstar
+
+typeit=0
+if [[ $1 == "--type" ]]; then
+ typeit=1
+ shift
+fi
+
+prefix=${PASSWORD_STORE_DIR-~/.password-store}
+password_files=( "$prefix"/**/*.gpg )
+password_files=( "${password_files[@]#"$prefix"/}" )
+password_files=( "${password_files[@]%.gpg}" )
+
+password=$(printf '%s\n' "${password_files[@]}" | dmenu "$@")
+
+[[ -n $password ]] || exit
+
+if [[ "$password" == *-otp ]]; then
+ otp='otp'
+fi
+
+if [[ $typeit -eq 0 ]]; then
+ pass $otp show -c "$password" 2>/dev/null
+else
+ pass $otp show "$password" | { IFS= read -r pass; printf %s "$pass"; } |
+ xdotool type --clearmodifiers --file -
+fi
diff --git a/modules/profiles/files/ssh-agent.service b/modules/profiles/files/ssh-agent.service
new file mode 100644
index 0000000..d49edc6
--- /dev/null
+++ b/modules/profiles/files/ssh-agent.service
@@ -0,0 +1,13 @@
+# https://unix.stackexchange.com/questions/339840/how-to-start-and-use-ssh-agent-as-systemd-service
+
+[Unit]
+Description=SSH key agent
+
+[Service]
+Type=simple
+Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
+# ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
+ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
+
+[Install]
+WantedBy=default.target
diff --git a/modules/profiles/lib/facter/pacman_version.rb b/modules/profiles/lib/facter/pacman_version.rb
new file mode 100644
index 0000000..1d17b04
--- /dev/null
+++ b/modules/profiles/lib/facter/pacman_version.rb
@@ -0,0 +1,7 @@
+Facter.add('pacman-version') do
+ if File.exists?('/bin/pacman') then
+ setcode do
+ `pacman -Qi pacman | awk -F' : ' '/^Version/ { print $2 }'`.strip()
+ end
+ end
+end
diff --git a/modules/profiles/manifests/dolphin.pp b/modules/profiles/manifests/dolphin.pp
new file mode 100644
index 0000000..f1fdcf8
--- /dev/null
+++ b/modules/profiles/manifests/dolphin.pp
@@ -0,0 +1,70 @@
+# Configure the file manager dolphin
+class profiles::dolphin {
+ ensure_packages ([
+ 'dolphin',
+ 'kde-cli-tools',
+ 'ffmpegthumbs',
+ 'kdegraphics-thumbnailers',
+ 'konsole',
+ 'breeze-icons',
+ ], { ensure => installed })
+
+
+ $dolphin_settings = {
+ 'General' => {
+ 'BrowseThroughArchives' => 'true',
+ 'GlobalViewProps' => 'false',
+ 'HomeUrl' => '/usr/net/video',
+ 'OpenExternallyCalledFolderInNewTab' => 'false',
+ 'RememberOpenedTabs' => 'false',
+ 'ShowFullPath' => 'true',
+ },
+ 'MainWindow' => {
+ 'MenuBar' => 'Disabled',
+ 'ToolBarsMovable' => 'Disabled',
+ },
+ 'VersionControl' => {
+ 'enabledPlugins' => [
+ 'Dropbox',
+ 'Git',
+ ]
+ },
+ 'PreviewSettings' => {
+ 'Plugins' => [
+ 'appimagethumbnail',
+ 'audiothumbnail',
+ 'blenderthumbnail',
+ 'comicbookthumbnail',
+ 'djvuthumbnail',
+ 'ebookthumbnail',
+ 'exrthumbnail',
+ 'directorythumbnail',
+ 'fontthumbnail',
+ 'imagethumbnail',
+ 'jpegthumbnail',
+ 'kraorathumbnail',
+ 'windowsexethumbnail',
+ 'windowsimagethumbnail',
+ 'opendocumentthumbnail',
+ 'gsthumbnail',
+ 'svgthumbnail',
+ 'textthumbnail',
+ 'ffmpegthumbs',
+ ]
+ }
+ }
+
+ $dolphin_settings.map |$category, $group| {
+ $group.map |$setting, $value| {
+ ini_setting { "Dolphin [${category}].${setting}":
+ path => '/etc/xdg/dolphinrc',
+ section => $category,
+ setting => $setting,
+ value => $value ? {
+ Array => $value.join(','),
+ String => $value,
+ }
+ }
+ }
+ }
+}
diff --git a/modules/profiles/manifests/firewall.pp b/modules/profiles/manifests/firewall.pp
new file mode 100644
index 0000000..6c9d7e6
--- /dev/null
+++ b/modules/profiles/manifests/firewall.pp
@@ -0,0 +1,19 @@
+class profiles::firewall {
+ ensure_packages ([
+ 'iptables-persistent',
+ 'fail2ban',
+ ], { ensure => installed })
+
+ file { '/etc/iptables/rules.v4':
+ source => 'puppet:///modules/profiles/firewall/rules.v4',
+ } ~> exec { 'reload firewall':
+ command => '/usr/share/netfilter-persistent/plugins.d/15-ip4tables restart',
+ refreshonly => true,
+ }
+
+ service { 'fail2ban':
+ ensure => running,
+ enable => true,
+ }
+
+}
diff --git a/modules/profiles/manifests/gandalf_web.pp b/modules/profiles/manifests/gandalf_web.pp
new file mode 100644
index 0000000..1295d83
--- /dev/null
+++ b/modules/profiles/manifests/gandalf_web.pp
@@ -0,0 +1,102 @@
+class profiles::gandalf_web (
+ String $certname,
+) {
+
+ class { '::nginx':
+ manage_repo => false,
+ # server_purge => true,
+ package_name => 'nginx-mainline',
+ service_config_check => true,
+ http_cfg_append => {
+ 'charset' => 'utf-8',
+ },
+ mime_types_preserve_defaults => true,
+ mime_types => {
+ 'text/plain' => 'wiki txt',
+ },
+ include_modules_enabled => true,
+ server_purge => true,
+ }
+
+ file { '/etc/nginx/modules-enabled':
+ ensure => directory,
+ purge => true,
+ recurse => true,
+ }
+
+ # TODO this fails at bootstrapping, since letsencrypt requires nginx
+ # to be enabled, but nginx can't be enabled if any cert file is
+ # missing
+ # Letsencrypt::Certonly <| |> -> Nginx::Resource::Server <| |>
+
+ $domains = [
+ 'bookmark.gandalf.adrift.space',
+ 'calendar.gandalf.adrift.space',
+ 'repo.gandalf.adrift.space',
+ 'gandalf.adrift.space',
+ 'hack.adrift.space',
+ 'adrift.space',
+ ]
+
+ ensure_packages (['cronie',], { ensure => installed })
+
+ ensure_packages (['certbot', 'certbot-nginx'], { ensure => installed })
+ class { '::letsencrypt':
+ config => {
+ email => 'hugo@hornquist.se',
+ # server => 'https://acme-staging-v02.api.letsencrypt.org/directory',
+ server => 'https://acme-v02.api.letsencrypt.org/directory',
+ },
+ manage_install => false,
+ }
+
+ letsencrypt::certonly { $certname:
+ ensure => present,
+ domains => $domains,
+ manage_cron => true,
+ plugin => 'nginx',
+ additional_args => [ '--quiet', ],
+ # pre_hook_commands => [ 'systemctl stop nginx.service', ],
+ post_hook_commands => [ 'systemctl restart nginx.service', ],
+ }
+
+
+ nginx::resource::server { 'gandalf':
+ ipv6_enable => true,
+ listen_options => 'default_server',
+ ipv6_listen_options => 'default_server',
+ server_name => [ '_' ],
+ access_log => absent,
+ error_log => absent,
+ ssl => true,
+ ssl_cert => "/etc/letsencrypt/live/${certname}/fullchain.pem",
+ ssl_key => "/etc/letsencrypt/live/${certname}/privkey.pem",
+ ssl_redirect => true,
+ index_files => [ 'index.html', ],
+ www_root => '/var/www/adrift.space',
+ use_default_location => false,
+ }
+
+ nginx::resource::location { '/':
+ try_files => ['$uri', '$uri/', '=404'],
+ index_files => [],
+ ssl => true,
+ ssl_only => true,
+ autoindex => on,
+ server => 'gandalf',
+ }
+
+ nginx::resource::server { 'repo.gandalf.adrift.space':
+ ipv6_enable => true,
+ ipv6_listen_options => '',
+ server_name => [ 'repo.gandalf.adrift.space', ],
+ ssl => true,
+ ssl_cert => "/etc/letsencrypt/live/${certname}/fullchain.pem",
+ ssl_key => "/etc/letsencrypt/live/${certname}/privkey.pem",
+ ssl_redirect => true,
+ index_files => [ 'index.html', ],
+ www_root => '/usr/net/repo/',
+ use_default_location => true,
+ }
+
+}
diff --git a/modules/profiles/manifests/group_profile.pp b/modules/profiles/manifests/group_profile.pp
new file mode 100644
index 0000000..2025a4b
--- /dev/null
+++ b/modules/profiles/manifests/group_profile.pp
@@ -0,0 +1,16 @@
+class profiles::group_profile {
+ file { '/etc/profile.d/group-env.sh':
+ ensure => 'file',
+ content => @(EOF)
+ for group in $(groups $(id -nu))
+ do
+ f="/etc/profile.d/group.d/${group}"
+ test -f "$f" && . $f
+ done
+ | EOF
+ }
+
+ file { '/etc/profile.d/group.d':
+ ensure => 'directory',
+ }
+}
diff --git a/modules/profiles/manifests/imagemagick.pp b/modules/profiles/manifests/imagemagick.pp
new file mode 100644
index 0000000..7663cf8
--- /dev/null
+++ b/modules/profiles/manifests/imagemagick.pp
@@ -0,0 +1,17 @@
+class profiles::imagemagick {
+ package { 'imagemagick':
+ ensure => installed,
+ }
+
+ file { '/etc/ImageMagick-7/policy.xml':
+ content => epp('profiles/imagemagick-policy.xml', {
+ policies => [
+ {
+ domain => 'coder',
+ rights => 'read | write',
+ pattern => 'PDF'
+ },
+ ]
+ }),
+ }
+}
diff --git a/modules/profiles/manifests/remarkable.pp b/modules/profiles/manifests/remarkable.pp
new file mode 100644
index 0000000..73ee5e7
--- /dev/null
+++ b/modules/profiles/manifests/remarkable.pp
@@ -0,0 +1,31 @@
+define profiles::remarkable (
+ String $prefix = '10.11.99',
+ String $addr = '2',
+) {
+
+ file_line { 'remarkable usb':
+ ensure => present,
+ path => '/etc/hosts',
+ line => "${prefix}.1 remarkable.usb",
+ }
+
+ file_line { 'remarkable usb self':
+ ensure => present,
+ path => '/etc/hosts',
+ line => "${prefix}.${addr} host.usb",
+ }
+
+ file { '/etc/systemd/network/25-remarkable-usb.network':
+ ensure => present,
+ content => @("EOF")
+ [Match]
+ Name=enp3s0f0u4
+
+ [Network]
+
+ Description=Remarkable USB connection
+ Address=${prefix}.${addr}/29
+ | EOF
+ }
+
+}
diff --git a/modules/profiles/manifests/syncthing.pp b/modules/profiles/manifests/syncthing.pp
new file mode 100644
index 0000000..7d8183e
--- /dev/null
+++ b/modules/profiles/manifests/syncthing.pp
@@ -0,0 +1,28 @@
+class profiles::syncthing (
+ Array[String] $enable_for = []
+) {
+
+ # TODO add repo for those systems that need it
+
+ package { 'syncthing':
+ ensure => installed
+ }
+
+ systemd::dropin_file { 'nospam.conf':
+ unit => 'syncthing@.service',
+ content => @(EOF)
+ [Service]
+ ExecStart=
+ ExecStart=/bin/bash -c 'set -o pipefail; /usr/bin/syncthing -no-browser -no-restart -logflags=0 | grep -v "INFO: "'
+ | EOF
+ }
+
+ $enable_for.map |$user| {
+ service { "syncthing@${user}":
+ enable => true,
+ }
+ }
+
+ # TODO manage synced data
+
+}
diff --git a/modules/profiles/manifests/synth.pp b/modules/profiles/manifests/synth.pp
new file mode 100644
index 0000000..eb01f8f
--- /dev/null
+++ b/modules/profiles/manifests/synth.pp
@@ -0,0 +1,33 @@
+class profiles::synth {
+
+ package { 'freepats-general-midi':
+ ensure => installed,
+ }
+
+ file { '/etc/conf.d/fluidsynth':
+ content => @(EOF)
+ SOUND_FONT=/usr/share/soundfonts/freepats-general-midi.sf2
+ OTHER_OPTS='-a alsa'
+ | EOF
+ }
+
+ # TODO pull in aur package from
+ # https://git.hornquist.se/archpkg/aconnect-service/
+
+ # TODO setup the rest
+
+ # - template:
+ # dest: ~/.config/aconnect/impact
+ # source: aconnect
+ # vars:
+ # input_unit: Impact LX25
+ # output_unit: FLUID Synth
+ #
+ # - systemd:
+ # name: aconnect@{{ impact }}
+ # scope: user
+ # enabled: yes
+ # become: yes
+ # become_user: hugo
+
+}
diff --git a/modules/profiles/manifests/transmission.pp b/modules/profiles/manifests/transmission.pp
new file mode 100644
index 0000000..f79517b
--- /dev/null
+++ b/modules/profiles/manifests/transmission.pp
@@ -0,0 +1,71 @@
+class profiles::transmission (
+ Optional[String] $nginx_server = undef,
+ Enum['None', 'Error', 'Info', 'Debug'] $msg_level = 'Error',
+) {
+
+ $transmission_url = '/transmission'
+ $transmission_port = 9091
+
+ if ($nginx_server) {
+ require ::nginx
+
+ nginx::resource::location { $transmission_url:
+ proxy => "http://localhost:${transmission_port}${transmission_url}",
+ proxy_set_header => [],
+ server => $nginx_server,
+ ssl => true,
+ ssl_only => true,
+ }
+ }
+
+ ensure_packages(['transmission-cli'],
+ { ensure => installed })
+
+ systemd::dropin_file { 'transmission-after.conf':
+ unit => 'transmission.service',
+ content => @(EOF)
+ [Unit]
+ After=network-online.target
+ | EOF
+ }
+
+ systemd::dropin_file { 'transmission-flags.conf':
+ unit => 'transmission.service',
+ content => @(EOF)
+ [Service]
+ ExecStart=
+ ExecStart=/usr/bin/transmission-daemon -f
+ | EOF
+ }
+
+ # TODO whitelists are currently disabled, since they don't seem to
+ # work. Possibly turn them on again some day.
+
+ # https://github.com/transmission/transmission/wiki/Editing-Configuration-File
+ file { '/var/lib/transmission/.config/transmission-daemon/settings.json':
+ content => epp('profiles/transmission.json.epp', {
+ rpc_username => 'hugo',
+ # '{' + sha1(password + salt)
+ # But I don't know how I managed to generate it, since
+ # transmission rolls its own crypto
+ rpc_password => '{eb43101d3b9aa02223466d7f98c5329c841c7967/Zr2tFpn',
+ download_dir => '/usr/net/',
+ rpc_whitelist => ['127.0.0.1', '::1'],
+ rpc_port => $transmission_port,
+ rpc_url => "${transmission_url}/",
+ msg_level => case $msg_level {
+ 'None': { 0 }
+ 'Error': { 1 }
+ 'Info': { 2 }
+ 'Debug': { 3 }
+ },
+ }),
+ } ~> exec { '/bin/systemctl reload transmission':
+ refreshonly => true,
+ }
+
+ service { 'transmission':
+ ensure => 'running',
+ enable => true,
+ }
+}
diff --git a/modules/profiles/manifests/webdav_server.pp b/modules/profiles/manifests/webdav_server.pp
new file mode 100644
index 0000000..2cd54c1
--- /dev/null
+++ b/modules/profiles/manifests/webdav_server.pp
@@ -0,0 +1,80 @@
+define profiles::webdav_server (
+ String $nginx_server,
+ String $file_path,
+ String $location = $name,
+ String $passwd_file = "${file_path}/.htpasswd",
+ String $owner = 'http',
+ String $group = 'share',
+ Array[Array[String,2,2]] $users = [],
+ Array[String] $dav_methods = ['PUT', 'DELETE', 'MKCOL', 'COPY', 'MOVE'],
+ Array[String] $dav_ext_methods = ['PROPFIND', 'OPTIONS'],
+ Hash[String,String] $dav_access = {
+ 'user' => 'rw',
+ 'group' => 'rw',
+ }
+) {
+
+ # TODO install this module somehow
+ # AUR: nginx-mainline-mod-dav-ext
+
+ require ::nginx
+
+ $modname = 'ngx_http_dav_ext_module'
+ file { "/etc/nginx/modules-enabled/${modname}.conf":
+ ensure => file,
+ content => @("EOF")
+ load_module /usr/lib/nginx/modules/${modname}.so;
+ | EOF
+ }
+
+ file {
+ default:
+ owner => $owner,
+ group => $group,
+ ;
+ $file_path:
+ ensure => 'directory',
+ mode => '0770',
+ recurse => 'false',
+ ;
+ $passwd_file:
+ ensure => 'file',
+ mode => '0660',
+ ;
+ }
+
+ # add entries to the htpasswd file through
+ # $ echo "${user}:$(openssl passwd -apr1 $password)" >> .htpasswd
+
+
+ $users.each |$pair| {
+ $user = $pair[0]
+ $passwd = $pair[1]
+ file_line { "Add ${user} to dav passwd file":
+ ensure => present,
+ path => $passwd_file,
+ line => "${user}:${passwd}",
+ match => "^${user}:"
+ }
+ }
+
+ nginx::resource::location { $location:
+ server => $nginx_server,
+ location_alias => $file_path,
+ ssl => true,
+ ssl_only => true,
+
+ auth_basic => 'Enter password for dav access',
+ auth_basic_user_file => $passwd_file,
+
+ location_cfg_append => {
+ 'dav_methods' => $dav_methods.join(' '),
+ 'dav_ext_methods' => $dav_ext_methods.join(' '),
+ 'dav_access' => $dav_access.map |$k, $v| { "${k}:${v}" }.join(' '),
+ 'client_body_temp_path' => "${file_path}/tmp",
+ 'create_full_put_path' => 'on',
+ 'autoindex' => 'on',
+ 'allow' => 'all',
+ }
+ }
+}
diff --git a/modules/profiles/manifests/workstation.pp b/modules/profiles/manifests/workstation.pp
new file mode 100644
index 0000000..fe7e1cb
--- /dev/null
+++ b/modules/profiles/manifests/workstation.pp
@@ -0,0 +1,132 @@
+class profiles::workstation {
+ $os = $facts['os']['name'].downcase()
+ include "::profiles::workstation::${os}"
+
+ include ::profiles::group_profile
+
+ # TODO only if we use systemd
+ file { 'User ssh-agent service':
+ path => '/etc/systemd/user/ssh-agent.service',
+ source => "puppet:///modules/profiles/ssh-agent.service",
+ }
+
+ file { 'Dvorak A6 TTY keyboard layout':
+ ensure => file,
+ path => '/usr/share/kbd/keymaps/i386/dvorak/dvorak-sv-a6.map',
+ source => 'https://raw.githubusercontent.com/HugoNikanor/keymaps/master/linux-tty/dvorak-sv-a6.map',
+ }
+
+ file { 'Dvorak A6 X11 keyboard layout':
+ ensure => file,
+ path => '/usr/share/X11/xkb/symbols/planck',
+ source => 'https://raw.githubusercontent.com/HugoNikanor/keymaps/master/X11/planck',
+ }
+
+ $xkb_layout = 'planck'
+ $xkb_variant = 'dvorak_a6'
+ $xkb_options = 'compose:caps'
+
+ file { 'Default X11 keymap':
+ ensure => file,
+ path => '/etc/X11/xorg.conf.d/00-keyboard.conf',
+ content => @("EOF")
+ Section "InputClass"
+ Identifier "system-keyboard"
+ MatchIsKeyboard "on"
+ Option "XkbLayout" "${xkb_layout}"
+ Option XkbModel "pc105"
+ Option "XkbVariant" "${xkb_variant}"
+ Option "XkbOptions" "${xkb_options}"
+ EndSection
+ | EOF
+ }
+
+ file { 'Model M X11 keymap':
+ ensure => file,
+ path => '/etc/X11/xorg.conf.d/01-model-m.conf',
+ content => @(EOF)
+ Section "InputClass"
+ Identifier "Model M"
+ MathUSBID "17f6:0822"
+ Option "XkbLayout" "us"
+ Option "XkbVariant" "dvorak"
+ EndSection
+ | EOF
+ }
+
+ file { 'Setup console':
+ ensure => file,
+ path => '/etc/vconsole.conf',
+ content => epp('profiles/keyvalue.epp', { 'values' => {
+ 'KEYMAP' => 'dvorak-sv-a6',
+ 'FONT' => 'lat9v-12',
+ }}),
+ }
+
+ $cowpath = [
+ '/usr/share/cows',
+ '/usr/local/share/cows',
+ ]
+
+ file { '/etc/environment':
+ content => epp('profiles/keyvalue.epp', { values => {
+ 'COWPATH' => $cowpath.join(':'),
+ 'MANWIDTH' => 80,
+ 'MPD_HOST' => 'jukebox.lysator.liu.se',
+ 'PAGER' => 'less',
+ 'EDITOR' => '/usr/bin/vi',
+ 'VISUAL' => '/usr/bin/vim',
+ }})
+ }
+
+ service { 'systemd-resolved':
+ enable => mask,
+ }
+
+ file { 'Passmenu with OTP support':
+ path => '/usr/local/bin/passmenu',
+ mode => '0555',
+ source => 'puppet:///modules/profiles/passmenu',
+ }
+
+ file { '/etc/sudoers':
+ validate_cmd => '/usr/bin/visudo -cf %',
+ content => @(EOF)
+ Defaults insults
+ root ALL=(ALL) ALL
+ %root ALL=(ALL) ALL
+ %wheel ALL=(ALL) ALL
+
+ @includedir /etc/sudoers.d
+ | EOF
+ }
+
+ $locales = [
+ 'en_DK.UTF-8 UTF-8',
+ 'en_US.UTF-8 UTF-8',
+ 'sv_SE.UTF-8 UTF-8',
+ 'sv_SE.ISO-8859-1 ISO-8859-1',
+ '',
+ ]
+
+ file { '/etc/locale.gen':
+ content => $locales.join("\n")
+ } ~> exec { 'locale-gen':
+ path => [ '/bin', '/usr/bin', ],
+ }
+
+ file { 'Default locales':
+ path => '/etc/locale.conf',
+ content => @(EOF)
+ LANG=en_US.UTF-8
+ LC_TIME=sv_SE.UTF-8
+ | EOF
+ }
+
+ $timezone = 'Europe/Stockholm'
+
+ file { '/etc/localtime':
+ ensure => link,
+ target => "/usr/share/zoneinfo/${timezone}",
+ }
+}
diff --git a/modules/profiles/manifests/workstation/archlinux.pp b/modules/profiles/manifests/workstation/archlinux.pp
new file mode 100644
index 0000000..5274699
--- /dev/null
+++ b/modules/profiles/manifests/workstation/archlinux.pp
@@ -0,0 +1,52 @@
+class profiles::workstation::archlinux {
+
+ pacman::hook { 'systemd daemon-reload':
+ description => 'Reload systemd user daemon',
+ exec => '/bin/sudo systemctl --machine=hugo@.host --user daemon-reload',
+ when => 'PostTransaction',
+ trigger => {
+ operation => 'Upgrade',
+ type => 'Path',
+ target => 'usr/lib/systemd/user/*',
+ },
+ }
+
+ package { 'kernel-modules-hook':
+ ensure => installed,
+ } ~> service { 'linux-modules-cleanup':
+ ensure => running,
+ enable => true,
+ }
+
+ $cpus = $facts['processors']['count'] - 1
+ file_line { 'Makepkg paralell':
+ path => '/etc/makepkg.conf',
+ after => '^#-- Make flags',
+ line => "MAKEFLAGS='-j${cpus}'"
+ }
+
+ pacman::repo { 'adrift-space':
+ ensure => present,
+ server => 'http://repo.gandalf.adrift.space/arch',
+ sig_level => 'Optional',
+ }
+
+ # remove
+ # - netctl
+
+ # aur-packages
+# - pacaur
+# - ansible-aur-git
+# - cyrus-sasl-xoauth2-git
+# - todotxt
+# - effitask
+# - getmail
+# - mu
+# # - pacaur
+# - pandoc-bin
+# - tlclient
+# # backups old modules on kernel update
+# - kernel-modules-hook
+
+
+}
diff --git a/modules/profiles/manifests/xmonad.pp b/modules/profiles/manifests/xmonad.pp
new file mode 100644
index 0000000..be8d516
--- /dev/null
+++ b/modules/profiles/manifests/xmonad.pp
@@ -0,0 +1,29 @@
+# Setup xmonad, only tested on arch linux
+class profiles::xmonad {
+ ensure_packages ([
+ 'xmonad',
+ 'xmonad-contrib',
+ # apparently really needed by xmonad
+ 'xorg-fonts-misc',
+ 'ghc',
+ 'xorg-xmessage',
+ 'dzen2',
+ 'dmenu',
+ 'rofi',
+ ], { ensure => installed })
+
+ # Rebuilt my local xmonad config after an upgrade to xmonad.
+ # It's required, I think due to something with dynamic linking.
+ # It's actually pretty ugly that I'm hardcoded in here, but
+ # something had to be done.
+ pacman::hook { 'xmonad':
+ description => 'Rebuild local xmonad config.',
+ when => 'PostTransaction',
+ exec => '/bin/sudo -Hu hugo xmonad --recompile',
+ trigger => {
+ type => 'Package',
+ operation => ['Upgrade', 'Install'],
+ target => 'xmonad*',
+ },
+ }
+}
diff --git a/modules/profiles/templates/aconnect.epp b/modules/profiles/templates/aconnect.epp
new file mode 100644
index 0000000..044ada6
--- /dev/null
+++ b/modules/profiles/templates/aconnect.epp
@@ -0,0 +1,8 @@
+<%- | String $input_unit,
+ String $output_unit
+| -%>
+# Where data comes from
+INPUT_UNIT='<%= $input_unit %>'
+# Where it should go
+OUTPUT_UNIT='<%= $output_unit %>'
+
diff --git a/modules/profiles/templates/imagemagick-policy.xml.epp b/modules/profiles/templates/imagemagick-policy.xml.epp
new file mode 100644
index 0000000..cbea9e9
--- /dev/null
+++ b/modules/profiles/templates/imagemagick-policy.xml.epp
@@ -0,0 +1,89 @@
+<%- | Array[Hash] $policies | -%>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policymap [
+ <!ELEMENT policymap (policy)*>
+ <!ATTLIST policymap xmlns CDATA #FIXED ''>
+ <!ELEMENT policy EMPTY>
+ <!ATTLIST policy xmlns CDATA #FIXED '' domain NMTOKEN #REQUIRED
+ name NMTOKEN #IMPLIED pattern CDATA #IMPLIED rights NMTOKEN #IMPLIED
+ stealth NMTOKEN #IMPLIED value CDATA #IMPLIED>
+]>
+<!--
+ Configure ImageMagick policies.
+
+ Domains include system, delegate, coder, filter, path, or resource.
+
+ Rights include none, read, write, execute and all. Use | to combine them,
+ for example: "read | write" to permit read from, or write to, a path.
+
+ Use a glob expression as a pattern.
+
+ Suppose we do not want users to process MPEG video images:
+
+ <policy domain="delegate" rights="none" pattern="mpeg:decode" />
+
+ Here we do not want users reading images from HTTP:
+
+ <policy domain="coder" rights="none" pattern="HTTP" />
+
+ The /repository file system is restricted to read only. We use a glob
+ expression to match all paths that start with /repository:
+
+ <policy domain="path" rights="read" pattern="/repository/*" />
+
+ Lets prevent users from executing any image filters:
+
+ <policy domain="filter" rights="none" pattern="*" />
+
+ Any large image is cached to disk rather than memory:
+
+ <policy domain="resource" name="area" value="1GP"/>
+
+ Use the default system font unless overwridden by the application:
+
+ <policy domain="system" name="font" value="/usr/share/fonts/favorite.ttf"/>
+
+ Define arguments for the memory, map, area, width, height and disk resources
+ with SI prefixes (.e.g 100MB). In addition, resource policies are maximums
+ for each instance of ImageMagick (e.g. policy memory limit 1GB, -limit 2GB
+ exceeds policy maximum so memory limit is 1GB).
+
+ Rules are processed in order. Here we want to restrict ImageMagick to only
+ read or write a small subset of proven web-safe image types:
+
+ <policy domain="delegate" rights="none" pattern="*" />
+ <policy domain="filter" rights="none" pattern="*" />
+ <policy domain="coder" rights="none" pattern="*" />
+ <policy domain="coder" rights="read|write" pattern="{GIF,JPEG,PNG,WEBP}" />
+-->
+<policymap>
+ <!-- Sample policies -->
+ <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
+ <!-- <policy domain="resource" name="memory" value="2GiB"/> -->
+ <!-- <policy domain="resource" name="map" value="4GiB"/> -->
+ <!-- <policy domain="resource" name="width" value="10KP"/> -->
+ <!-- <policy domain="resource" name="height" value="10KP"/> -->
+ <!-- <policy domain="resource" name="list-length" value="128"/> -->
+ <!-- <policy domain="resource" name="area" value="100MP"/> -->
+ <!-- <policy domain="resource" name="disk" value="16EiB"/> -->
+ <!-- <policy domain="resource" name="file" value="768"/> -->
+ <!-- <policy domain="resource" name="thread" value="4"/> -->
+ <!-- <policy domain="resource" name="throttle" value="0"/> -->
+ <!-- <policy domain="resource" name="time" value="3600"/> -->
+ <!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
+ <!-- <policy domain="module" rights="none" pattern="{PS,PDF,XPS}" /> -->
+ <!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
+ <!-- <policy domain="path" rights="none" pattern="@*" /> -->
+ <!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
+ <!-- <policy domain="cache" name="synchronize" value="True"/> -->
+ <!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
+ <!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
+ <!-- <policy domain="system" name="shred" value="2"/> -->
+ <!-- <policy domain="system" name="precision" value="6"/> -->
+ <!-- <policy domain="system" name="font" value="/path/to/unicode-font.ttf"/> -->
+ <!-- Below policies generated from puppet -->
+ <% $policies.map |$policy| { %>
+ <policy domain="<%= $policy['domain'] %>" rights="<%= $policy['rights'] %>" pattern="<%= $policy['pattern'] %>" />
+ <%- } %>
+</policymap>
+<!-- NOTE File managed by puppet, any manual changes will be overwritten. -->
diff --git a/modules/profiles/templates/keyvalue.epp b/modules/profiles/templates/keyvalue.epp
new file mode 100644
index 0000000..694978a
--- /dev/null
+++ b/modules/profiles/templates/keyvalue.epp
@@ -0,0 +1,4 @@
+<%- | Hash $values | -%>
+<% $values.map |$key, $value| { -%>
+<%= $key %>=<%= $value %>
+<%- } %>
diff --git a/modules/profiles/templates/transmission.json.epp b/modules/profiles/templates/transmission.json.epp
new file mode 100644
index 0000000..885ad5e
--- /dev/null
+++ b/modules/profiles/templates/transmission.json.epp
@@ -0,0 +1,77 @@
+<%- | String $rpc_username,
+ String $rpc_password,
+ String $download_dir,
+ Integer $rpc_port,
+ String $rpc_url,
+ Integer $msg_level = 1,
+ Optional[String] $incomplete_dir = undef,
+ Optional[Array[String]] $rpc_whitelist = undef,
+| -%>
+{
+ "alt-speed-down": 50,
+ "alt-speed-enabled": false,
+ "alt-speed-time-begin": 540,
+ "alt-speed-time-day": 127,
+ "alt-speed-time-enabled": false,
+ "alt-speed-time-end": 1020,
+ "alt-speed-up": 50,
+ "bind-address-ipv4": "0.0.0.0",
+ "bind-address-ipv6": "::",
+ "blocklist-enabled": false,
+ "blocklist-url": "http://www.example.com/blocklist",
+ "cache-size-mb": 4,
+ "dht-enabled": true,
+ "download-dir": "<%= $download_dir -%>",
+ "download-queue-enabled": true,
+ "download-queue-size": 5,
+ "encryption": 1,
+ "idle-seeding-limit": 30,
+ "idle-seeding-limit-enabled": false,
+ "incomplete-dir": "<%= $incomplete_dir -%>",
+ "incomplete-dir-enabled": <%= if ($incomplete_dir) { 'true' } else { 'false' } -%>,
+ "lpd-enabled": false,
+ "message-level": <%= $msg_level -%>,
+ "peer-congestion-algorithm": "",
+ "peer-id-ttl-hours": 6,
+ "peer-limit-global": 200,
+ "peer-limit-per-torrent": 50,
+ "peer-port": 51413,
+ "peer-port-random-high": 65535,
+ "peer-port-random-low": 49152,
+ "peer-port-random-on-start": false,
+ "peer-socket-tos": "default",
+ "pex-enabled": true,
+ "port-forwarding-enabled": true,
+ "preallocation": 1,
+ "prefetch-enabled": true,
+ "queue-stalled-enabled": true,
+ "queue-stalled-minutes": 30,
+ "ratio-limit": 2,
+ "ratio-limit-enabled": false,
+ "rename-partial-files": true,
+ "rpc-authentication-required": true,
+ "rpc-bind-address": "::",
+ "rpc-enabled": true,
+ "rpc-host-whitelist": "",
+ "rpc-host-whitelist-enabled": false,
+ "rpc-password": "<%= $rpc_password -%>",
+ "rpc-port": <%= $rpc_port -%>,
+ "rpc-url": "<%= $rpc_url -%>",
+ "rpc-username": "<%= $rpc_username -%>",
+ "rpc-whitelist": "<%= $rpc_whitelist.join(',') -%>",
+ "rpc-whitelist-enabled": <%= if ($rpc_whitelist) { 'false' } else { 'false' }-%>,
+ "scrape-paused-torrents-enabled": true,
+ "script-torrent-done-enabled": false,
+ "script-torrent-done-filename": "",
+ "seed-queue-enabled": false,
+ "seed-queue-size": 10,
+ "speed-limit-down": 100,
+ "speed-limit-down-enabled": false,
+ "speed-limit-up": 100,
+ "speed-limit-up-enabled": false,
+ "start-added-torrents": true,
+ "trash-original-torrent-files": false,
+ "umask": 18,
+ "upload-slots-per-torrent": 14,
+ "utp-enabled": true
+}