├── LICENSE ├── README.md ├── ansible.cfg ├── bin ├── bootstrap_void ├── link_paths └── setup_ssh_key ├── dotfiles ├── .Xresources ├── .dunstrc ├── .spectrwm.conf ├── .spectrwm.keys ├── .xinitrc ├── .xmodmaprc └── screenshot.sh ├── group_vars ├── all ├── laptop └── void ├── host_vars └── malort ├── hosts ├── laptop.yml └── roles ├── av └── tasks │ ├── install_spotify.yml │ ├── main.yml │ └── mpd.yml ├── c └── tasks │ └── main.yml ├── clojure └── tasks │ └── main.yml ├── common ├── files │ ├── exec_dir │ └── pirate.cow └── tasks │ ├── install_essentials.yml │ ├── install_runit.yml │ ├── install_ssh_keys.yml │ ├── local_known_hosts.yml │ ├── main.yml │ ├── packaging.yml │ ├── root_cron.yml │ ├── root_stuff.yml │ └── user_cron.yml ├── dev └── tasks │ ├── install_dirs.yml │ ├── install_editors.yml │ ├── install_misc.yml │ ├── install_networking.yml │ └── main.yml ├── erlang ├── handlers │ └── main.yml └── tasks │ └── main.yml ├── games └── tasks │ ├── dwarf_fortress.yml │ ├── install_steam.yml │ └── main.yml ├── git_homedir ├── handlers │ └── main.yml └── tasks │ └── main.yml ├── j └── tasks │ └── main.yml ├── k └── tasks │ └── main.yml ├── laptop ├── files │ └── X1C6_S3_DSDT.patch ├── handlers │ └── main.yml └── tasks │ ├── acpi_events.yml │ ├── hardware.yml │ └── main.yml ├── lisp └── tasks │ └── main.yml ├── lua └── tasks │ └── main.yml ├── ocaml └── tasks │ └── main.yml ├── phone ├── files │ └── 90-android-phone-in-plugdev-group.rules ├── handlers │ └── main.yml └── tasks │ └── main.yml ├── prolog └── tasks │ └── main.yml ├── python └── tasks │ └── main.yml ├── virtualization └── tasks │ └── main.yml ├── void ├── files │ └── clear-xbps-pkg-cache └── tasks │ └── main.yml ├── wifi └── tasks │ └── main.yml └── x11 ├── files └── 20-keyboard_dvorak.conf └── tasks ├── install_web_browsers.yml ├── install_x11_void.yml └── main.yml /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Scott Vokes 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example Ansible-based setup for a 6th gen. Thinkpad X1 Carbon 2 | 3 | ## Summary 4 | 5 | This repository contains an [Ansible][a] playbook and set of roles for 6 | configuring a [Void Linux][v] installation on a 6th Gen. ThinkPad X1 7 | Carbon laptop. It's extracted from my private `ansible_config` repo, 8 | which I also use to configure several other systems. Hopefully it's 9 | useful as an example of using Ansible to configure personal stuff, 10 | and/or documentation for configuring Linux for this particular laptop. 11 | 12 | Note that I don't cover installing Void itself -- I didn't really need 13 | to do anything special to get things working, though. I had to disable 14 | Secure Boot in the BIOS, used a USB flash drive to install, and had an 15 | USB ethernet adapter on hand. That was about it. (It should be possible 16 | to install over wifi, but I haven't tried.) 17 | 18 | [v]: https://voidlinux.org/ 19 | [a]: https://www.ansible.com/ 20 | 21 | 22 | ### What's Ansible? 23 | 24 | Ansible is a configuration management tool, similar to Chef, Puppet, or 25 | Salt. It reads info about how to configure system(s), then generates 26 | scripts which connect over ssh and figure out whether anything needs to 27 | change. Then, the scripts report back, and optionally make the changes. 28 | 29 | Rather than saying "install this, then add this line to its config 30 | file", the config is framed as "this should be present; the config file 31 | should contain this line". That way, steps that have already completed 32 | can be skipped, and small updates can be applied quickly. 33 | 34 | Because Ansible is pushing scripts, rather than waiting for an agent on 35 | every system to pull and apply updates, it scales down nicely to 36 | personal use cases. 37 | 38 | I wrote a couple blog posts about using Ansible at a previous job: 39 | 40 | - https://spin.atomicobject.com/2015/02/21/ansible-git-directory/ 41 | - https://spin.atomicobject.com/2015/09/21/ansible-configuration-management-laptop/ 42 | - https://spin.atomicobject.com/2015/09/22/ansible-config-example/ 43 | 44 | While Ansible has had several interface changes since then (for example, 45 | the `sudo` setting is now named `become`, and no longer specific to 46 | `sudo`), it's usually pretty good about suggesting replacements for 47 | deprecated keywords, and those posts should still be conceptually 48 | accurate. 49 | 50 | 51 | ## Contents 52 | 53 | - install some tools I use almost everywhere 54 | 55 | - set up root and user cron directories (e.g. `~/bin/cron/hourly.d/`) 56 | crontab entries for them, and a script that runs any files in them 57 | 58 | - install local incoming ssh keys 59 | 60 | - install packages for Void man pages, logging, sshd, ntpd 61 | 62 | - set the package mirror, console font, and timezone 63 | 64 | - set the keyboard layout to Dvorak 65 | 66 | - register ACPI event handlers for the laptop's mute, volume, and 67 | brightness buttons 68 | 69 | - hardware-related configuration to enable Suspend (S3), adjust the CPU 70 | overtemp throttling, and install microcode updates 71 | 72 | - setting up wifi (using `connmanctl`) 73 | 74 | - install some language-independent development tools 75 | 76 | - install and configure an x11 tiling window manager (spectrwm), 77 | launcher (dmenu), and a relatively minimal notification daemon (dunst) 78 | 79 | 80 | Also several optional things, which are controlled by flags/options in 81 | `host_vars`, and disabled by default: 82 | 83 | - install a git repo as the user homedir (with dotfiles, etc.) 84 | 85 | - install tooling for any of several programming languages I use: C, 86 | Clojure, Erlang, J, k (Kona), Lisp (SBCL), Lua, Scheme (Chez, Chicken), OCaml, 87 | Prolog (SWI), Python 88 | 89 | - install audio/video players (mplayer, mpd, the Spotify client) 90 | 91 | - install some games (nethack, Steam, Dwarf Fortress) 92 | 93 | - install tools to mount an Android phone's filesystem over USB (note 94 | that you'll need to log in again for group changes to take effect) 95 | 96 | There are a couple things that would normally be configured via dotfiles 97 | in my git homedir -- I've put relevant files in `dotfiles/` instead. 98 | 99 | 100 | ## Setup Instructions 101 | 102 | - Clone the repo. 103 | 104 | - `cd` to the base directory of the checkout. 105 | 106 | - Run `bin/bootstrap_void`, which will install a couple things using `su`, 107 | and enable sudo for the current user. 108 | 109 | - Log out and log back in, so group changes take effect (allowing `sudo`). 110 | 111 | - Because Void is a rolling release distro, you might need to update the 112 | system packages a couple times before it reaches a fixpoint. 113 | 114 | To update, run: 115 | 116 | $ sudo xbps-install -Su 117 | 118 | until it no longer asks about updating packages. 119 | 120 | - Optional: run `setup_ssh_key` to generate an ssh key and automatically 121 | add it to `install_ssh_keys.yml` in the `common` role. I use the same 122 | set of roles for other computers besides this laptop, so that way my 123 | ssh public keys automatically get added to `~/.ssh/authorized_keys` on 124 | the others. 125 | 126 | - Run `bin/link_paths`, to symlink some Ansible config files in the repo 127 | to a subdir in `/etc`, where Ansible will look for them. This probably 128 | isn't a good idea in a production setting, but it's very convenient 129 | for personal use. (To see which files, look at the script.) 130 | 131 | $ bin/link_paths /etc/ansible 132 | 133 | - Edit the hosts file to add the name of the laptop to _both_ the 134 | `[laptop]` and `[void]` groups. This informs Ansible that it should 135 | consider them in both groups, and use their corresponding settings 136 | in `group_vars/` (`all`, `laptop`, `void`). 137 | 138 | - Optionally, create a host-specific config file under `host_vars`. 139 | This overrides the other settings from group vars. 140 | 141 | - Run the Ansible playbook, using `ansible-playbook`: 142 | 143 | $ ansible-playbook -l ${LAPTOP_NAME} -K laptop.yml 144 | 145 | This will prompt for the sudo password once, upfront, and then begin 146 | installing stuff. (`-K` is `--ask-become-pass`, where "become" is 147 | Ansible's wrapper for use `sudo`, `doas`, and similar tools). 148 | 149 | (Note: Ansible will pipe messages through cowsay, once present.) 150 | 151 | - Optionally, edit the host-specific config file in `host_vars` 152 | and re-run Ansible. Anything that's already done will be quickly 153 | skipped, but new settings will be applied, until it converges on 154 | the new configuration. 155 | 156 | 157 | ## Misc. Ansible Notes 158 | 159 | Ansible functionality is grouped into modules, like `file`, `copy`, 160 | `git`, `lineinfile`, and OS-specific packaging modules like `xbps`, 161 | `apt`, and `openbsd_pkg`. `ansible-doc ` will print interface 162 | notes for a particular module, and `ansible-doc -l` will list the 163 | available modules. 164 | 165 | Rather than using several `.yml` files in the base directory, the 166 | config is gathered into several subdirectories, called roles. For more 167 | info, see the [Asible docs for 'role'][r]. 168 | 169 | [r]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html 170 | 171 | If anything fails, then `ansible-playbook` can be re-run with a 172 | `--start "task name"` argument to resume at a particular task, 173 | and `--step` can be used to pause and prompt after each step. 174 | 175 | `--list-tasks` will list all the tasks in the playbook. 176 | 177 | 178 | ## The Laptop 179 | 180 | This laptop works really well with Linux. Suspend didn't work by 181 | default, but that's fixed in `roles/laptop/tasks/hardware.yml`, and 182 | everything else has been straightforward to set up. 183 | 184 | I strongly prefer its keyboard to any of the newer Apple laptops' 185 | keyboards (particularly the touchbar models), and it has a trackpoint & 186 | three mouse buttons. It's noticeably lighter than a MacBook Pro, without 187 | feeling fragile. 188 | 189 | Various forums recommended disabling the external microSD / SIM card 190 | port in BIOS. (Apparently it uses an unusually high amount of power when 191 | idle, and the SIM card isn't supported anyway.) `powertop` can be used 192 | to identify other things that are disproportionately impacting battery 193 | life. 194 | 195 | There's other info about hardware support at the 196 | [Arch wiki](https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X1_Carbon_(Gen_6)). 197 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | error_on_undefined_vars=true 3 | 4 | [ssh_connection] 5 | ssh_args = -o ForwardAgent=yes 6 | -------------------------------------------------------------------------------- /bin/bootstrap_void: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # bootstrap Void Linux on a LOCAL host 4 | LOCAL_USER=${USER} 5 | 6 | echo "Installing sudo, ansible, and sshpass, and adding local user." 7 | echo "This will prompt for the su password..." 8 | su -c 'xbps-install -S sudo ansible sshpass && usermod -a -G wheel ${LOCAL_USER}' 9 | 10 | echo "Note: you will need to log back in for the group change to take effect." 11 | -------------------------------------------------------------------------------- /bin/link_paths: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Set the hosts file (inventory) and group and host vars directories 4 | # to point into the VC'd repo. For more about the inventory, see 5 | # https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html 6 | # 7 | # If you don't want to symlink this, it can be set via ansible-playbook's 8 | # `-i` (`--inventory`) option. 9 | 10 | ANSIBLE_BASE=$1 11 | PWD=$(pwd) 12 | 13 | if [ -z ${ANSIBLE_BASE} ]; then 14 | echo "Usage: $0 ANSIBLE_BASE" 15 | echo "e.g. $0 /etc/ansible" 16 | echo "ansible-playbook's default location for 'hosts' is usually /etc/ansible" 17 | else 18 | # make ansible dir if it doesn't exist 19 | if [ ! -d ${ANSIBLE_BASE} ]; then 20 | echo "Making directory ${ANSIBLE_BASE} using sudo" 21 | sudo mkdir ${ANSIBLE_BASE} 22 | fi 23 | 24 | echo "Creating symlinks within ${ANSIBLE_BASE} using sudo" 25 | sudo ln -s ${PWD}/hosts ${ANSIBLE_BASE}/hosts 26 | sudo ln -s ${PWD}/group_vars/ ${ANSIBLE_BASE}/group_vars 27 | sudo ln -s ${PWD}/host_vars/ ${ANSIBLE_BASE}/host_vars 28 | fi 29 | -------------------------------------------------------------------------------- /bin/setup_ssh_key: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PUB_KEY_PATH="${HOME}/.ssh/id_rsa.pub" 4 | 5 | PLAYBOOK_BASE_PATH="$1" 6 | YML_PATH="${PLAYBOOK_BASE_PATH}/roles/common/tasks/install_ssh_keys.yml" 7 | 8 | if [ -e "${YML_PATH}" ]; then 9 | if [ -e ${PUB_KEY_PATH} ]; then 10 | echo "SSH key ${PUB_KEY_PATH} already exists, skipping key creation." 11 | else 12 | echo "Running ssh-keygen with the defaults..." 13 | ssh-keygen 14 | fi 15 | 16 | # TODO: make idempotent 17 | echo Adding public key to Ansible playbook 18 | cat ${PUB_KEY_PATH} | awk ' 19 | { 20 | "hostname" | getline hostname 21 | printf("- name: install SSH key (%s)\n", hostname) 22 | printf(" become: no\n") 23 | printf(" authorized_key:\n") 24 | printf(" key: \"%s\"\n", $0) 25 | printf(" user: \"{{ansible_user_id}}\"\n") 26 | printf(" state: present\n") 27 | printf("\n") 28 | } 29 | ' >> ${YML_PATH} 30 | else 31 | echo "Usage: $0 (may be .)" 32 | fi 33 | -------------------------------------------------------------------------------- /dotfiles/.Xresources: -------------------------------------------------------------------------------- 1 | *.foreground: white 2 | *.background: black 3 | 4 | URxvt.font: xft:terminus:size=16:antialias=true 5 | URxvt.boldFont: xft:terminus bold:size=16:antialias=true 6 | URxvt.scrollBar: 0 7 | -------------------------------------------------------------------------------- /dotfiles/.dunstrc: -------------------------------------------------------------------------------- 1 | [global] 2 | ### Display ### 3 | 4 | # Which monitor should the notifications be displayed on. 5 | monitor = 0 6 | 7 | # Display notification on focused monitor. Possible modes are: 8 | # mouse: follow mouse pointer 9 | # keyboard: follow window with keyboard focus 10 | # none: don't follow anything 11 | # 12 | # "keyboard" needs a window manager that exports the 13 | # _NET_ACTIVE_WINDOW property. 14 | # This should be the case for almost all modern window managers. 15 | # 16 | # If this option is set to mouse or keyboard, the monitor option 17 | # will be ignored. 18 | follow = keyboard 19 | 20 | # The geometry of the window: 21 | # [{width}]x{height}[+/-{x}+/-{y}] 22 | # The geometry of the message window. 23 | # The height is measured in number of notifications everything else 24 | # in pixels. If the width is omitted but the height is given 25 | # ("-geometry x2"), the message window expands over the whole screen 26 | # (dmenu-like). If width is 0, the window expands to the longest 27 | # message displayed. A positive x is measured from the left, a 28 | # negative from the right side of the screen. Y is measured from 29 | # the top and down respectively. 30 | # The width can be negative. In this case the actual width is the 31 | # screen width minus the width defined in within the geometry option. 32 | geometry = "300x5-30+20" 33 | 34 | # Show how many messages are currently hidden (because of geometry). 35 | indicate_hidden = yes 36 | 37 | # Shrink window if it's smaller than the width. Will be ignored if 38 | # width is 0. 39 | shrink = no 40 | 41 | # The transparency of the window. Range: [0; 100]. 42 | # This option will only work if a compositing window manager is 43 | # present (e.g. xcompmgr, compiz, etc.). 44 | transparency = 0 45 | 46 | # The height of the entire notification. If the height is smaller 47 | # than the font height and padding combined, it will be raised 48 | # to the font height and padding. 49 | notification_height = 0 50 | 51 | # Draw a line of "separator_height" pixel height between two 52 | # notifications. 53 | # Set to 0 to disable. 54 | separator_height = 2 55 | 56 | # Padding between text and separator. 57 | padding = 8 58 | 59 | # Horizontal padding. 60 | horizontal_padding = 8 61 | 62 | # Defines width in pixels of frame around the notification window. 63 | # Set to 0 to disable. 64 | frame_width = 3 65 | 66 | # Defines color of the frame around the notification window. 67 | frame_color = "#aaaaaa" 68 | 69 | # Define a color for the separator. 70 | # possible values are: 71 | # * auto: dunst tries to find a color fitting to the background; 72 | # * foreground: use the same color as the foreground; 73 | # * frame: use the same color as the frame; 74 | # * anything else will be interpreted as a X color. 75 | separator_color = frame 76 | 77 | # Sort messages by urgency. 78 | sort = yes 79 | 80 | # Don't remove messages, if the user is idle (no mouse or keyboard input) 81 | # for longer than idle_threshold seconds. 82 | # Set to 0 to disable. 83 | # Transient notifications ignore this setting. 84 | idle_threshold = 120 85 | 86 | ### Text ### 87 | 88 | font = Terminus 24 89 | 90 | # The spacing between lines. If the height is smaller than the 91 | # font height, it will get raised to the font height. 92 | line_height = 0 93 | 94 | # Possible values are: 95 | # full: Allow a small subset of html markup in notifications: 96 | # bold 97 | # italic 98 | # strikethrough 99 | # underline 100 | # 101 | # For a complete reference see 102 | # . 103 | # 104 | # strip: This setting is provided for compatibility with some broken 105 | # clients that send markup even though it's not enabled on the 106 | # server. Dunst will try to strip the markup but the parsing is 107 | # simplistic so using this option outside of matching rules for 108 | # specific applications *IS GREATLY DISCOURAGED*. 109 | # 110 | # no: Disable markup parsing, incoming notifications will be treated as 111 | # plain text. Dunst will not advertise that it has the body-markup 112 | # capability if this is set as a global setting. 113 | # 114 | # It's important to note that markup inside the format option will be parsed 115 | # regardless of what this is set to. 116 | markup = full 117 | 118 | # The format of the message. Possible variables are: 119 | # %a appname 120 | # %s summary 121 | # %b body 122 | # %i iconname (including its path) 123 | # %I iconname (without its path) 124 | # %p progress value if set ([ 0%] to [100%]) or nothing 125 | # %n progress value if set without any extra characters 126 | # %% Literal % 127 | # Markup is allowed 128 | format = "%s\n%b" 129 | 130 | # Alignment of message text. 131 | # Possible values are "left", "center" and "right". 132 | alignment = left 133 | 134 | # Show age of message if message is older than show_age_threshold 135 | # seconds. 136 | # Set to -1 to disable. 137 | show_age_threshold = 60 138 | 139 | # Split notifications into multiple lines if they don't fit into 140 | # geometry. 141 | word_wrap = yes 142 | 143 | # When word_wrap is set to no, specify where to ellipsize long lines. 144 | # Possible values are "start", "middle" and "end". 145 | ellipsize = middle 146 | 147 | # Ignore newlines '\n' in notifications. 148 | ignore_newline = no 149 | 150 | # Merge multiple notifications with the same content 151 | stack_duplicates = true 152 | 153 | # Hide the count of merged notifications with the same content 154 | hide_duplicate_count = false 155 | 156 | # Display indicators for URLs (U) and actions (A). 157 | show_indicators = yes 158 | 159 | ### Icons ### 160 | 161 | # Align icons left/right/off 162 | icon_position = off 163 | 164 | # Scale larger icons down to this size, set to 0 to disable 165 | max_icon_size = 32 166 | 167 | # Paths to default icons. 168 | icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ 169 | 170 | ### History ### 171 | 172 | # Should a notification popped up from history be sticky or timeout 173 | # as if it would normally do. 174 | sticky_history = yes 175 | 176 | # Maximum amount of notifications kept in history 177 | history_length = 20 178 | 179 | ### Misc/Advanced ### 180 | 181 | # dmenu path. 182 | dmenu = /usr/bin/dmenu -p dunst: 183 | 184 | # Browser for opening urls in context menu. 185 | browser = /usr/bin/firefox -new-tab 186 | 187 | # Always run rule-defined scripts, even if the notification is suppressed 188 | always_run_script = true 189 | 190 | # Define the title of the windows spawned by dunst 191 | title = Dunst 192 | 193 | # Define the class of the windows spawned by dunst 194 | class = Dunst 195 | 196 | # Print a notification on startup. 197 | # This is mainly for error detection, since dbus (re-)starts dunst 198 | # automatically after a crash. 199 | startup_notification = false 200 | 201 | ### Legacy 202 | 203 | # Use the Xinerama extension instead of RandR for multi-monitor support. 204 | # This setting is provided for compatibility with older nVidia drivers that 205 | # do not support RandR and using it on systems that support RandR is highly 206 | # discouraged. 207 | # 208 | # By enabling this setting dunst will not be able to detect when a monitor 209 | # is connected or disconnected which might break follow mode if the screen 210 | # layout changes. 211 | force_xinerama = false 212 | 213 | # Experimental features that may or may not work correctly. Do not expect them 214 | # to have a consistent behaviour across releases. 215 | [experimental] 216 | # Calculate the dpi to use on a per-monitor basis. 217 | # If this setting is enabled the Xft.dpi value will be ignored and instead 218 | # dunst will attempt to calculate an appropriate dpi value for each monitor 219 | # using the resolution and physical size. This might be useful in setups 220 | # where there are multiple screens with very different dpi values. 221 | per_monitor_dpi = false 222 | 223 | [shortcuts] 224 | 225 | # Shortcuts are specified as [modifier+][modifier+]...key 226 | # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2", 227 | # "mod3" and "mod4" (windows-key). 228 | # Xev might be helpful to find names for keys. 229 | 230 | # Close notification. ('d' for dismiss) 231 | close = mod4+d 232 | 233 | # Close all notifications. 234 | close_all = mod4+shift+d 235 | 236 | # Redisplay last message(s). 237 | # On the US keyboard layout "grave" is normally above TAB and left 238 | # of "1". Make sure this key actually exists on your keyboard layout, 239 | # e.g. check output of 'xmodmap -pke' 240 | history = mod4+grave 241 | 242 | # Context menu. 243 | #context = mod4+ctrl+shift+d 244 | 245 | [urgency_low] 246 | # IMPORTANT: colors have to be defined in quotation marks. 247 | # Otherwise the "#" and following would be interpreted as a comment. 248 | background = "#222222" 249 | foreground = "#888888" 250 | timeout = 10 251 | # Icon for notifications with low urgency, uncomment to enable 252 | #icon = /path/to/icon 253 | 254 | [urgency_normal] 255 | background = "#004040" 256 | foreground = "#ffffff" 257 | timeout = 10 258 | # Icon for notifications with normal urgency, uncomment to enable 259 | #icon = /path/to/icon 260 | 261 | [urgency_critical] 262 | background = "#900000" 263 | foreground = "#ffffff" 264 | frame_color = "#ff0000" 265 | timeout = 0 266 | # Icon for notifications with critical urgency, uncomment to enable 267 | #icon = /path/to/icon 268 | 269 | # Every section that isn't one of the above is interpreted as a rules to 270 | # override settings for certain messages. 271 | # Messages can be matched by "appname", "summary", "body", "icon", "category", 272 | # "msg_urgency" and you can override the "timeout", "urgency", "foreground", 273 | # "background", "new_icon" and "format". 274 | # Shell-like globbing will get expanded. 275 | # 276 | # SCRIPTING 277 | # You can specify a script that gets run when the rule matches by 278 | # setting the "script" option. 279 | # The script will be called as follows: 280 | # script appname summary body icon urgency 281 | # where urgency can be "LOW", "NORMAL" or "CRITICAL". 282 | # 283 | # NOTE: if you don't want a notification to be displayed, set the format 284 | # to "". 285 | # NOTE: It might be helpful to run dunst -print in a terminal in order 286 | # to find fitting options for rules. 287 | 288 | #[espeak] 289 | # summary = "*" 290 | # script = dunst_espeak.sh 291 | 292 | #[script-test] 293 | # summary = "*script*" 294 | # script = dunst_test.sh 295 | 296 | #[ignore] 297 | # # This notification will not be displayed 298 | # summary = "foobar" 299 | # format = "" 300 | 301 | #[history-ignore] 302 | # # This notification will not be saved in history 303 | # summary = "foobar" 304 | # history_ignore = yes 305 | 306 | #[signed_on] 307 | # appname = Pidgin 308 | # summary = "*signed on*" 309 | # urgency = low 310 | # 311 | #[signed_off] 312 | # appname = Pidgin 313 | # summary = *signed off* 314 | # urgency = low 315 | # 316 | #[says] 317 | # appname = Pidgin 318 | # summary = *says* 319 | # urgency = critical 320 | # 321 | #[twitter] 322 | # appname = Pidgin 323 | # summary = *twitter.com* 324 | # urgency = normal 325 | # 326 | # vim: ft=cfg 327 | -------------------------------------------------------------------------------- /dotfiles/.spectrwm.conf: -------------------------------------------------------------------------------- 1 | # NOTE: all rgb color values in this file are in hex! see XQueryColor for examples 2 | 3 | workspace_limit = 10 4 | # focus_mode = default 5 | # focus_close = previous 6 | # focus_close_wrap = 1 7 | # focus_default = last 8 | # spawn_position = next 9 | 10 | # Window Decoration 11 | # border_width = 1 12 | color_focus = rgb:10/60/60 13 | # color_focus_maximized = yellow 14 | color_unfocus = rgb:20/20/20 15 | # color_unfocus_maximized = rgb:88/88/00 16 | # region_padding = 0 17 | # tile_gap = 0 18 | 19 | # Bar Settings 20 | # bar_enabled = 1 21 | # bar_border_width = 1 22 | bar_border[1] = rgb:10/30/30 23 | bar_color[1] = rgb:20/20/20 24 | # bar_border_unfocus[1] = rgb:00/40/40 25 | bar_font_color[1] = rgb:c0/c0/c0 26 | bar_font = -*-terminus-medium-r-normal-*-24-*-*-*-*-*-*-* 27 | bar_action = statusline 28 | # bar_justify = left 29 | bar_format = +I +S +2<%a %b %d %Y %R +2<+A 30 | bar_at_bottom = 1 31 | # stack_enabled = 1 32 | clock_enabled = 1 33 | clock_format = %a %b %d %R %Z %Y 34 | iconic_enabled = 1 35 | # window_class_enabled = 0 36 | # window_instance_enabled = 0 37 | # window_name_enabled = 0 38 | # verbose_layout = 1 39 | # urgent_enabled = 1 40 | 41 | # Dialog box size ratio when using TRANSSZ quirk; 0.3 < dialog_ratio <= 1.0 42 | dialog_ratio = 0.6 43 | 44 | # Mod key, (Windows key is Mod4) (Apple key on OSX is Mod2) 45 | modkey = Mod4 46 | 47 | # Validated default programs: 48 | # program[lock] = xlock 49 | program[term] = urxvt 50 | program[menu] = dmenu_run -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_border -sf rgb:f0/f0/f0 51 | 52 | # set Mod4+c to copy: xsel | xclip -in 53 | # set Mod4+v to paste: xclip -out | xvkbd -xsendevent -file - >/dev/null 54 | program[kbd_copy] = sh -c 'xsel | xclip -in' 55 | program[kbd_paste] = sh -c 'xclip -out | xvkbd -xsendevent -file - >/dev/null' 56 | 57 | # Optional default programs that will only be validated if you override: 58 | program[screenshot_all] = screenshot.sh full # optional 59 | program[screenshot_wind] = screenshot.sh window # optional 60 | # program[initscr] = initscreen.sh # optional 61 | 62 | # Reset the keyboard mappings 63 | keyboard_mapping = ~/.spectrwm.keys 64 | 65 | # QUIRKS - figure out class / name with xprop 66 | # Default quirks, remove with: quirk[class:name] = NONE 67 | quirk[MPlayer] = FLOAT + FULLSCREEN + FOCUSPREV 68 | quirk[Gimp:gimp] = FLOAT + ANYWHERE 69 | quirk[inkscape] = FLOAT + ANYWHERE 70 | quirk[Qiv:qiv] = FLOAT + FULLSCREEN 71 | quirk[lupe:lupe] = FLOAT 72 | quirk[Firefox-bin:firefox-bin] = TRANSSZ 73 | quirk[Firefox:Dialog] = FLOAT 74 | quirk[xwrits:xwrits] = FLOAT + ANYWHERE + TRANSSZ + NOFOCUSONMAP 75 | quirk[xev:xev] = FLOAT 76 | 77 | # Android is quirky 78 | quirk[Android SDK Manager] = FLOAT + ANYWHERE 79 | 80 | -------------------------------------------------------------------------------- /dotfiles/.spectrwm.keys: -------------------------------------------------------------------------------- 1 | bind[term] = MOD+Shift+Return 2 | bind[menu] = MOD+p 3 | bind[quit] = MOD+Shift+q 4 | bind[restart] = MOD+q 5 | 6 | bind[bar_toggle] = MOD+b 7 | bind[bar_toggle_ws] = MOD+Shift+b 8 | 9 | bind[cycle_layout] = MOD+space 10 | bind[flip_layout] = MOD+Shift+backslash 11 | bind[float_toggle] = MOD+t 12 | bind[focus_main] = MOD+m 13 | bind[focus_next] = MOD+j 14 | bind[screen_next] = MOD+Tab 15 | 16 | bind[height_grow] = MOD+Shift+equal 17 | bind[height_shrink] = MOD+Shift+minus 18 | # bind[iconify] = MOD+w 19 | bind[initscr] = MOD+Shift+i 20 | 21 | bind[master_add] = MOD+comma 22 | bind[master_del] = MOD+period 23 | bind[master_grow] = MOD+l 24 | bind[master_shrink] = MOD+h 25 | # bind[maximize_toggle] = MOD+e 26 | 27 | bind[move_down] = MOD+Shift+bracketright 28 | bind[move_left] = MOD+bracketleft 29 | bind[move_right] = MOD+bracketright 30 | bind[move_up] = MOD+Shift+bracketleft 31 | 32 | bind[screenshot_all] = MOD+s 33 | bind[screenshot_wind] = MOD+Shift+s 34 | bind[kbd_copy] = MOD+c 35 | bind[kbd_paste] = MOD+v 36 | 37 | bind[swap_main] = MOD+Return 38 | 39 | # bind[uniconify] = MOD+Shift+w 40 | bind[width_grow] = MOD+equal 41 | bind[width_shrink] = MOD+minus 42 | bind[wind_del] = MOD+x 43 | bind[wind_kill] = MOD+Shift+x 44 | 45 | bind[ws_1] = MOD+1 46 | bind[ws_2] = MOD+2 47 | bind[ws_3] = MOD+3 48 | bind[ws_4] = MOD+4 49 | bind[ws_5] = MOD+5 50 | bind[ws_6] = MOD+6 51 | bind[ws_7] = MOD+7 52 | bind[ws_8] = MOD+8 53 | bind[ws_9] = MOD+9 54 | bind[ws_10] = MOD+0 55 | 56 | bind[mvws_1] = MOD+Shift+1 57 | bind[mvws_2] = MOD+Shift+2 58 | bind[mvws_3] = MOD+Shift+3 59 | bind[mvws_4] = MOD+Shift+4 60 | bind[mvws_5] = MOD+Shift+5 61 | bind[mvws_6] = MOD+Shift+6 62 | bind[mvws_7] = MOD+Shift+7 63 | bind[mvws_8] = MOD+Shift+8 64 | bind[mvws_9] = MOD+Shift+9 65 | bind[mvws_10] = MOD+Shift+0 66 | -------------------------------------------------------------------------------- /dotfiles/.xinitrc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | xsetroot -solid black 3 | 4 | HOSTNAME=$(hostname -s) 5 | 6 | if [ -e ~/.Xresources ]; then 7 | xrdb -load ~/.Xresources & 8 | fi 9 | 10 | if [ -e ~/.Xresources.${HOSTNAME} ]; then 11 | xrdb -load ~/.Xresources.${HOSTNAME} & 12 | fi 13 | 14 | if [ -e ~/.xmodmaprc ]; then 15 | xmodmap ~/.xmodmaprc & 16 | fi 17 | 18 | # mouse 19 | xset m 5 10 20 | 21 | # bell length and pitch 22 | xset b 100 400 25 23 | 24 | # turn displays off after 10 minutes idle 25 | xset s off 26 | xset +dpms 27 | xset dpms 0 600 650 28 | 29 | # notifications 30 | if [ -e ~/.dunstrc ]; then 31 | type dunst > /dev/null && dunst -conf ~/.dunstrc & 32 | fi 33 | 34 | exec spectrwm 35 | -------------------------------------------------------------------------------- /dotfiles/.xmodmaprc: -------------------------------------------------------------------------------- 1 | ! http://efod.se/writings/linuxbook/html/caps-lock-to-ctrl.html 2 | keycode 66 = Control_L 3 | clear Lock 4 | add Control = Control_L 5 | keycode 117 = Page_Down 6 | add Lock = Caps_Lock 7 | -------------------------------------------------------------------------------- /dotfiles/screenshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MODE="$1" 4 | OUT="$HOME/tmp/screenshot-$(date "+%Y-%m-%dT%H:%M:%S%z").png" 5 | 6 | if [ "$MODE" = full ]; then 7 | import -adjoin -screen -window root -silent ${OUT} 8 | elif [ "$MODE" = window ]; then 9 | active_window=$(xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)" | sed -e "s/.* 0x/0x/") 10 | import -window "${active_window}" ${OUT} 11 | else 12 | # interactive selection 13 | import -silent ${OUT} 14 | fi 15 | 16 | -------------------------------------------------------------------------------- /group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | gnu_make: make 3 | 4 | is_desktop: false 5 | is_laptop: false 6 | 7 | run_sshd: false 8 | use_x11: false 9 | 10 | # override these in host_vars 11 | host_timezone: America/Detroit 12 | 13 | install_git_homedir: false 14 | preferred_shell: oksh 15 | 16 | install_av: false 17 | install_games: false 18 | install_virtualization: false 19 | 20 | install_c: false 21 | install_clojure: false 22 | install_erlang: false 23 | install_lisp: false 24 | install_lua: false 25 | install_ocaml: false 26 | install_prolog: false 27 | install_python: false 28 | install_ruby: false 29 | install_j: false 30 | install_k: false 31 | 32 | install_phone_tools: false 33 | 34 | install_spotify: false 35 | install_steam: false 36 | install_dwarf_fortress: false 37 | -------------------------------------------------------------------------------- /group_vars/laptop: -------------------------------------------------------------------------------- 1 | --- 2 | has_root: true 3 | has_runit: true 4 | is_laptop: true 5 | ansible_connection: local 6 | -------------------------------------------------------------------------------- /group_vars/void: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # any OS-specific vars would go here 4 | -------------------------------------------------------------------------------- /host_vars/malort: -------------------------------------------------------------------------------- 1 | --- 2 | run_sshd: true 3 | use_x11: true 4 | 5 | graphics_card: i915 6 | sound_card: 'hda-intel' 7 | 8 | install_git_homedir: true 9 | vc_host_path: example.com/vc 10 | git_homedir_repo_name: homedir 11 | 12 | install_av: true 13 | install_games: true 14 | install_phone_tools: true 15 | 16 | install_c: true 17 | install_erlang: true 18 | install_lua: true 19 | install_python: true 20 | install_j: true 21 | install_k: true 22 | 23 | mpd_dir: /home/music/ 24 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | # see: http://docs.ansible.com/intro_inventory.html 2 | 3 | [laptop] 4 | malort 5 | 6 | [void] 7 | malort 8 | -------------------------------------------------------------------------------- /laptop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: laptop 3 | roles: 4 | - common 5 | - { role: void, when: ansible_distribution == "void" } 6 | - laptop 7 | - { role: git_homedir, when: install_git_homedir } 8 | - { role: x11, when: use_x11 } 9 | - dev 10 | - { role: phone, when: install_phone_tools } 11 | - wifi 12 | 13 | # programming languages / platforms 14 | - { role: c, when: install_c } 15 | - { role: clojure, when: install_clojure } 16 | - { role: erlang, when: install_erlang } 17 | - { role: j, when: install_j } 18 | - { role: k, when: install_k } 19 | - { role: lisp, when: install_lisp } 20 | - { role: lua, when: install_lua } 21 | - { role: ocaml, when: install_ocaml } 22 | - { role: prolog, when: install_prolog } 23 | - { role: python, when: install_python } 24 | 25 | # other conditional roles 26 | - { role: av, when: install_av } 27 | - { role: games, when: install_games } 28 | - { role: virtualization, when: install_virtualization } 29 | -------------------------------------------------------------------------------- /roles/av/tasks/install_spotify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install nonfree void repo 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: void-repo-nonfree 8 | state: present 9 | 10 | - name: update void package cache 11 | become: yes 12 | when: ansible_os_family == "void" 13 | xbps: 14 | update_cache: yes 15 | 16 | - name: install spotify app 17 | become: yes 18 | when: ansible_os_family == "void" 19 | xbps: 20 | name: spotify 21 | state: latest 22 | -------------------------------------------------------------------------------- /roles/av/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install AV stuff 3 | become: yes 4 | when: ansible_distribution == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - mplayer 10 | - mpg123 11 | - alsa-lib 12 | - alsa-utils 13 | 14 | - name: enable hda-intel sound card 15 | become: yes 16 | when: ansible_distribution == "void" and sound_card is defined and sound_card == "hda-intel" 17 | lineinfile: 18 | path: /etc/modprobe.d/snd-hda-intel.conf 19 | line: "options snd-hda-intel model=auto" 20 | state: present 21 | create: yes 22 | 23 | - name: ensure user is in audio group 24 | become: yes 25 | when: ansible_os_family == "void" 26 | user: 27 | append: yes 28 | groups: audio 29 | name: '{{ansible_user_id}}' 30 | 31 | - name: install other audio dependencies 32 | become: yes 33 | when: ansible_distribution == "void" 34 | xbps: 35 | name: "{{item}}" 36 | state: latest 37 | with_items: 38 | - dbus 39 | 40 | - name: enable services (void) 41 | become: yes 42 | when: ansible_distribution == "void" 43 | file: 44 | src: "/etc/sv/{{item}}" 45 | dest: "/var/service/{{item}}" 46 | state: link 47 | with_items: 48 | - dbus 49 | - alsa 50 | 51 | - name: set up mpd and music 52 | include: mpd.yml 53 | when: mpd_dir is defined 54 | 55 | - name: install spotify 56 | include: install_spotify.yml 57 | when: install_spotify 58 | -------------------------------------------------------------------------------- /roles/av/tasks/mpd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install mpd and clients 4 | become: yes 5 | when: ansible_distribution == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - mpd 11 | - ncmpc 12 | - mpc 13 | 14 | - name: enable mpd services (void) 15 | become: yes 16 | when: ansible_distribution == "void" 17 | file: 18 | src: "/etc/sv/{{item}}" 19 | dest: "/var/service/{{item}}" 20 | state: link 21 | with_items: 22 | - mpd 23 | 24 | - name: ensure music directory exists and uses audio group 25 | become: yes 26 | file: 27 | path: '{{ mpd_dir }}' 28 | state: directory 29 | owner: '{{ansible_user_id}}' 30 | group: audio 31 | mode: 0750 32 | recurse: yes 33 | 34 | - name: set mpd music directory 35 | become: yes 36 | lineinfile: 37 | dest: /etc/mpd.conf 38 | backup: yes 39 | state: present 40 | regexp: ^music_directory 41 | line: music_directory "{{mpd_dir}}" 42 | 43 | - name: set mpd music port 44 | become: yes 45 | lineinfile: 46 | dest: /etc/mpd.conf 47 | backup: yes 48 | state: present 49 | regexp: ^#?bind_to_address 50 | line: bind_to_address "127.0.0.1" 51 | 52 | - name: add mpd user to audio 53 | become: yes 54 | when: ansible_distribution == "void" 55 | user: 56 | append: yes 57 | name: mpd 58 | groups: audio 59 | 60 | - name: ensure alsa pulseaudio plugin is present 61 | become: yes 62 | when: ansible_distribution == "void" 63 | xbps: 64 | name: alsa-plugins-pulseaudio 65 | state: present 66 | 67 | # This seemed to become necessary after an upstream change to mpd, 68 | # apparently; it seems possibly related to 69 | # http://mailman.blarg.de/pipermail/mpd-devel/2016-June/000523.html 70 | # I think it's trying to use sndio, which isn't configured properly, 71 | # whereas it previously defaulted to alsa/pulseaudio (which worked)? 72 | # 73 | # This works on my machine, at least, and is an exmaple of the 74 | # blockinfile module. 75 | - name: configure mpd to use alsa and pulseaudio 76 | become: yes 77 | when: ansible_distribution == "void" 78 | blockinfile: 79 | path: /etc/mpd.conf 80 | backup: yes 81 | insertafter: "# An example of an ALSA output:" 82 | block: | 83 | audio_output { 84 | type "alsa" 85 | name "My ALSA Device" 86 | device "pulse" 87 | } 88 | -------------------------------------------------------------------------------- /roles/c/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install C related tooling (Void) 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - afl 11 | - astyle 12 | - gcc 13 | - gdb 14 | - clang 15 | - clang-analyzer 16 | - valgrind 17 | -------------------------------------------------------------------------------- /roles/clojure/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install clojure and related tooling (Void) 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - clojure 11 | - leiningen 12 | -------------------------------------------------------------------------------- /roles/common/files/exec_dir: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: $0 DIR" 5 | else 6 | DIR="$1" 7 | if [ -e ${DIR} ]; then 8 | TASKS=$(ls -1 ${DIR}) 9 | 10 | if [ -n "${TASKS}" ]; then 11 | for task in ${TASKS}; do 12 | ${DIR}/${task} 13 | done 14 | fi 15 | fi 16 | fi 17 | -------------------------------------------------------------------------------- /roles/common/files/pirate.cow: -------------------------------------------------------------------------------- 1 | $eye = chop($eyes); 2 | $the_cow = <<"EOC"; 3 | $thoughts A__^ 4 | $thoughts ($eye#)\\_______ 5 | (__)\\ )\\/\\ 6 | $tongue ||----w | 7 | J| |V 8 | EOC 9 | -------------------------------------------------------------------------------- /roles/common/tasks/install_essentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # install essential stuff 3 | 4 | - name: install essentials (void) 5 | become: yes 6 | when: ansible_os_family == "void" 7 | xbps: 8 | name: "{{item}}" 9 | state: present 10 | with_items: 11 | - ansible 12 | - apg 13 | - bzip2 14 | - cowsay 15 | - figlet 16 | - git-all 17 | - make 18 | - patch 19 | - pwgen 20 | - rsync 21 | - runit 22 | - sqlite 23 | - tmux 24 | - unzip 25 | - zip 26 | 27 | - name: install pirate cow (void) 28 | become: yes 29 | when: ansible_os_family == "void" 30 | copy: 31 | src: pirate.cow 32 | dest: /usr/share/cows/pirate.cow 33 | owner: root 34 | group: root 35 | mode: 0644 36 | -------------------------------------------------------------------------------- /roles/common/tasks/install_runit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # on Void, runit is installed by default 4 | -------------------------------------------------------------------------------- /roles/common/tasks/install_ssh_keys.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install SSH key (malort) 4 | become: no 5 | authorized_key: 6 | key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEvcC0HnNpyhlSWjQrHZIft0bkZtRuBHEVwPiTaRch52u7ChLk2xxCdzUA7rmyTCUnJTTw70GoP1edrjjzSm+pegeoKT/CGdNP7ktoGfe7ydnJZ/FybxLETIqX4NfQOquW75Z6uO6o0jmeN11VruhQsGXwbsWtEhlEnExcQl4yzeZwcaS2++N7zSE3jrYtwM/yVj4ML/EmCIF6BZpLSDQlJ5VewVMEivcXaUh5HI2OBMqOpOu2wH4o65A3Mk04QzJcjJO5Ld2u0SVFzqYQhsRL01RNMV1uGjj6zjezR+w7LxDM7u+DL8jZtH+9J2UgD7XFVwKwiUKU9SeD8U1M7b7F scott@malort" 7 | user: "{{ansible_user_id}}" 8 | state: present 9 | 10 | -------------------------------------------------------------------------------- /roles/common/tasks/local_known_hosts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | ## not available in 1.7.2, new in 1.9 4 | # - name: set known_hosts for shenani.gen.nz 5 | # known_hosts: 6 | # name: shenani.gen.nz 7 | # state: present 8 | # key: "shenani.gen.nz ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC44PrUjH84X3wpP+GtYI0QeKfRt++ISMNpaP8pYtjn6wkAgT+fJaSM/s2jzeQI1uv8kw+48Ga8u3Cz3kyLKDywpaWPEOfnfFd7RqMC7OioiovfdpevC0Jjeb1UlW69OR1qqPISiYKWM62KVsgYV8XkqjFav3F7lo4zOSrshEjft+V65cTBBdJw4hipGjlmM9t+1+l7dImiHgQFeGWLGjDMlDe7WPSxMtnuMMIFyFPwdFXdjkfLFzAGQDwUy1XQtq42SO0S1kDA+SPV2ffJwOpHkiVmCQR3v4pp4SSf0UMnl7gSPnaWJzUpN3Tp6ksTdbQLZ4zDPpYmUeT7UlG5SQ9P" 9 | -------------------------------------------------------------------------------- /roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: trace become_method 4 | when: become_method is defined 5 | debug: 6 | var: become_method 7 | 8 | - name: install ssh keys 9 | import_tasks: install_ssh_keys.yml 10 | 11 | - name: stuff that needs root access 12 | when: has_root is defined 13 | import_tasks: root_stuff.yml 14 | 15 | - name: set up cron for the user 16 | import_tasks: user_cron.yml 17 | -------------------------------------------------------------------------------- /roles/common/tasks/packaging.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: update Void package cache 4 | when: ansible_os_family == "void" 5 | become: yes 6 | xbps: 7 | update_cache: yes 8 | -------------------------------------------------------------------------------- /roles/common/tasks/root_cron.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: add bin dir for root 4 | become: yes 5 | file: path="/root/bin/" state="directory" 6 | 7 | - name: configure cron for root 8 | become: yes 9 | file: path="/root/bin/cron/" state="directory" 10 | 11 | - name: copy exec_dir script (root) 12 | become: yes 13 | copy: src="exec_dir" mode="0744" dest="/root/bin/exec_dir" 14 | 15 | # Void doesn't have a cron daemon installed by default 16 | - name: install dcron on void 17 | when: ansible_distribution == "void" 18 | become: yes 19 | xbps: 20 | name: dcron 21 | state: present 22 | 23 | - name: enable dcron service on void 24 | when: ansible_distribution == "void" 25 | become: yes 26 | file: 27 | state: link 28 | src: /etc/sv/dcron 29 | dest: /var/service/dcron 30 | owner: root 31 | group: root 32 | 33 | # Note: dcron's aliases like @hourly don't work here, because it 34 | # requires an extra `ID=name` field, which is used for creating a 35 | # timestamp file (in case the system isn't on all the time). Ansible 36 | # doesn't have a way to configure that field. Just use numeric time 37 | # settings instead. 38 | - name: configure parametric cron directories for root 39 | become: yes 40 | cron: 41 | name: "exec_dir {{item}}" 42 | special_time: "{{item}}" 43 | job: "/root/bin/exec_dir /root/bin/cron/{{item}}.d" 44 | with_items: 45 | - reboot 46 | 47 | - name: configure yearly 48 | become: yes 49 | cron: 50 | name: "exec_dir yearly" 51 | minute: 0 52 | hour: 1 53 | month: 1 54 | day: 1 55 | job: "/root/bin/exec_dir /root/bin/cron/yearly.d" 56 | 57 | - name: configure monthly 58 | become: yes 59 | cron: 60 | name: "exec_dir monthly" 61 | minute: 0 62 | hour: 2 63 | day: 1 64 | job: "/root/bin/exec_dir /root/bin/cron/monthly.d" 65 | 66 | - name: configure weekly 67 | become: yes 68 | cron: 69 | name: "exec_dir weekly" 70 | minute: 0 71 | hour: 3 72 | weekday: 0 73 | job: "/root/bin/exec_dir /root/bin/cron/weekly.d" 74 | 75 | - name: configure daily 76 | become: yes 77 | cron: 78 | name: "exec_dir daily" 79 | minute: 15 80 | hour: 0 81 | job: "/root/bin/exec_dir /root/bin/cron/daily.d" 82 | 83 | - name: configure hourly 84 | become: yes 85 | cron: 86 | name: "exec_dir hourly" 87 | minute: 0 88 | job: "/root/bin/exec_dir /root/bin/cron/hourly.d" 89 | 90 | - name: configure minutely 91 | become: yes 92 | cron: 93 | name: "exec_dir minutely" 94 | minute: "0-59" 95 | job: "/root/bin/exec_dir /root/bin/cron/minutely.d" 96 | -------------------------------------------------------------------------------- /roles/common/tasks/root_stuff.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: set up packaging / mirror stuff 4 | include: packaging.yml 5 | 6 | - name: set up cron for root 7 | include: root_cron.yml 8 | 9 | - name: install essentials 10 | include: install_essentials.yml 11 | -------------------------------------------------------------------------------- /roles/common/tasks/user_cron.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: configure cron for user 3 | file: path="{{ansible_env.HOME}}/bin/cron/" state="directory" 4 | 5 | - name: copy exec_dir script (user) 6 | copy: src="exec_dir" mode="0744" dest="{{ansible_env.HOME}}/bin/exec_dir" 7 | 8 | - name: add parametric cron directories for user 9 | cron: 10 | name: "exec {{item}} dir" 11 | special_time: "{{item}}" 12 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/{{item}}.d" 13 | with_items: 14 | - reboot 15 | 16 | - name: configure yearly 17 | cron: 18 | name: "exec yearly dir" 19 | minute: 0 20 | hour: 1 21 | month: 1 22 | day: 1 23 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/yearly.d" 24 | 25 | - name: configure monthly 26 | cron: 27 | name: "exec monthly dir" 28 | minute: 0 29 | hour: 2 30 | day: 1 31 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/monthly.d" 32 | 33 | - name: configure weekly 34 | cron: 35 | name: "exec weekly dir" 36 | minute: 0 37 | hour: 3 38 | weekday: 0 39 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/weekly.d" 40 | 41 | - name: configure daily 42 | cron: 43 | name: "exec daily dir" 44 | minute: 15 45 | hour: 0 46 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/daily.d" 47 | 48 | - name: configure hourly 49 | cron: 50 | name: "exec hourly dir" 51 | minute: 0 52 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/hourly.d" 53 | 54 | - name: configure minutely (which has no special_time abbrev) 55 | cron: 56 | name: "exec minutely dir" 57 | minute: 0-59 58 | job: "{{ansible_env.HOME}}/bin/exec_dir {{ansible_env.HOME}}/bin/cron/minutely.d" 59 | 60 | - name: remove inconsistently named minutely task 61 | cron: 62 | name: "exec minutely" 63 | state: absent 64 | -------------------------------------------------------------------------------- /roles/dev/tasks/install_dirs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create directories 3 | become: no 4 | file: 5 | path: "{{item}}" 6 | state: "directory" 7 | owner: '{{ansible_user_id}}' 8 | with_items: 9 | - "{{ansible_env.HOME}}/tmp/" 10 | - "{{ansible_env.HOME}}/tmp/git/" 11 | - "{{ansible_env.HOME}}/tmp/src/" 12 | - "{{ansible_env.HOME}}/bin/" 13 | - "{{ansible_env.HOME}}/dev/" 14 | -------------------------------------------------------------------------------- /roles/dev/tasks/install_editors.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install editors (void) 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - emacs-x11 11 | - vim 12 | -------------------------------------------------------------------------------- /roles/dev/tasks/install_misc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install misc dev tools 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - make 11 | - bmake 12 | - discount 13 | - git-all 14 | - graphviz 15 | - mscgen 16 | - perf 17 | - strace 18 | 19 | -------------------------------------------------------------------------------- /roles/dev/tasks/install_networking.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install networking tools (void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - arp-scan 10 | - curl 11 | - ii 12 | - nmap 13 | - rsync 14 | - wget 15 | - bind-utils 16 | 17 | - name: install networking tools (void, x11) 18 | become: yes 19 | when: ansible_os_family == "void" and use_x11 20 | xbps: 21 | name: "{{item}}" 22 | state: latest 23 | with_items: 24 | - wireshark-qt 25 | 26 | - name: add the current user to the group wireshark 27 | become: true 28 | when: ansible_os_family == "void" and use_x11 29 | user: 30 | append: yes 31 | groups: wireshark 32 | name: '{{ansible_user_id}}' 33 | -------------------------------------------------------------------------------- /roles/dev/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Development stuff that isn't language-specific 4 | 5 | - name: install dirs 6 | include: install_dirs.yml 7 | 8 | - name: install editors 9 | include: install_editors.yml 10 | 11 | - name: install networking tools 12 | include: install_networking.yml 13 | 14 | - name: install misc 15 | include: install_misc.yml 16 | -------------------------------------------------------------------------------- /roles/erlang/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install rebar3 4 | copy: 5 | src: "{{ansible_env.HOME}}/tmp/git/rebar3/rebar3" 6 | dest: "{{ansible_env.HOME}}/bin/rebar3" 7 | remote_src: yes 8 | -------------------------------------------------------------------------------- /roles/erlang/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install Erlang related tooling (Void) 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - erlang 11 | 12 | - name: ensure destination directories exist (Erlang) 13 | file: 14 | path: "{{item}}" 15 | state: directory 16 | with_items: 17 | - "{{ansible_env.HOME}}/tmp/git/" 18 | - "{{ansible_env.HOME}}/bin/" 19 | 20 | - name: clone rebar3 21 | git: 22 | repo: https://github.com/erlang/rebar3.git 23 | dest: "{{ansible_env.HOME}}/tmp/git/rebar3" 24 | update: no 25 | accept_hostkey: true 26 | 27 | - name: build rebar3 28 | command: ./bootstrap 29 | args: 30 | chdir: "{{ansible_env.HOME}}/tmp/git/rebar3" 31 | creates: "{{ansible_env.HOME}}/tmp/git/rebar3/rebar3" 32 | notify: 33 | - install rebar3 34 | 35 | # this is void-specific because different distros install 36 | # the man pages in different paths 37 | - name: add Erlang man pages to manpath (void) 38 | become: yes 39 | when: ansible_os_family == "void" 40 | lineinfile: 41 | path: /etc/man.conf 42 | line: "manpath /usr/lib/erlang/man/" 43 | create: yes 44 | -------------------------------------------------------------------------------- /roles/games/tasks/dwarf_fortress.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install dwarf fortress dependencies (void) 4 | when: ansible_distribution == "void" 5 | become: yes 6 | xbps: 7 | name: '{{item}}' 8 | with_items: 9 | - SDL_image 10 | - SDL_ttf 11 | - libopenal 12 | - glu 13 | 14 | - name: download dwarf fortress (Linux) 15 | when: ansible_system == "Linux" 16 | get_url: 17 | dest: "{{ansible_env.HOME}}/tmp/df_44_11_linux.tar.bz2" 18 | url: http://www.bay12games.com/dwarves/df_44_11_linux.tar.bz2 19 | sha256sum: 4e13652d0b9c9a88bdc9628d50ef60ab944930497f131dc1b1d74c41fb743fe2 20 | 21 | - name: unpack dwarf fortress (Linux) 22 | when: ansible_system == "Linux" 23 | unarchive: 24 | src: "{{ansible_env.HOME}}/tmp/df_44_11_linux.tar.bz2" 25 | dest: "{{ansible_env.HOME}}/bin/" 26 | creates: "{{ansible_env.HOME}}/bin/df_linux/df" 27 | 28 | - name: add script to start dwarf fortress (Linux) 29 | when: ansible_system == "Linux" 30 | blockinfile: 31 | path: "{{ansible_env.HOME}}/bin/dwarf_fortress" 32 | create: yes 33 | mode: 0700 34 | block: | 35 | #!/bin/sh 36 | cd ~/bin/df_linux && ./df 37 | -------------------------------------------------------------------------------- /roles/games/tasks/install_steam.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install nonfree void repo for steam 4 | become: yes 5 | when: ansible_distribution == "void" 6 | xbps: 7 | name: void-repo-nonfree 8 | state: present 9 | 10 | - name: install multilib void repo 11 | become: yes 12 | when: ansible_distribution == "void" 13 | xbps: 14 | name: void-repo-multilib 15 | state: present 16 | 17 | - name: update void package cache 18 | when: ansible_distribution == "void" 19 | become: yes 20 | xbps: 21 | update_cache: yes 22 | 23 | - name: install multilib packages for steam 24 | when: ansible_distribution == "void" 25 | become: yes 26 | xbps: 27 | name: "{{item}}" 28 | state: present 29 | with_items: 30 | - libpulseaudio-32bit 31 | - libtxc_dxtn-32bit 32 | - fontconfig-32bit 33 | - libGL-32bit 34 | - mesa-ati-dri-32bit 35 | - mono 36 | 37 | - name: install steam 38 | when: ansible_distribution == "void" 39 | become: yes 40 | xbps: 41 | name: "{{item}}" 42 | state: present 43 | with_items: 44 | - steam 45 | -------------------------------------------------------------------------------- /roles/games/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install various games and emulators (void) 3 | when: ansible_distribution == "void" 4 | become: yes 5 | xbps: 6 | name: "{{item}}" 7 | state: present 8 | with_items: 9 | - nethack 10 | - higan 11 | 12 | - name: install steam 13 | include: install_steam.yml 14 | when: install_steam 15 | 16 | - name: dwarf fortress 17 | include: dwarf_fortress.yml 18 | when: install_dwarf_fortress 19 | -------------------------------------------------------------------------------- /roles/git_homedir/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install homedir 4 | synchronize: 5 | src: '{{ansible_env.HOME}}/dev/homedir/' 6 | dest: '{{ansible_env.HOME}}' 7 | recursive: yes 8 | delegate_to: '{{ansible_hostname}}' 9 | 10 | - name: fix homedir permissions 11 | file: 12 | path: '{{ansible_env.HOME}}' 13 | mode: 0700 14 | -------------------------------------------------------------------------------- /roles/git_homedir/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: clone homedir git repo in ~ 4 | when: vc_host_path is defined 5 | git: 6 | repo: 'ssh://{{vc_host_path}}/{{git_homedir_repo_name}}' 7 | dest: '{{ansible_env.HOME}}/dev/homedir/' 8 | update: no 9 | accept_hostkey: true 10 | notify: 11 | - install homedir 12 | - fix homedir permissions 13 | -------------------------------------------------------------------------------- /roles/j/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: ensure destination directories exist (j) 4 | file: 5 | path: "{{item}}" 6 | state: directory 7 | with_items: 8 | - "{{ansible_env.HOME}}/tmp/git/" 9 | - "{{ansible_env.HOME}}/bin/" 10 | 11 | - name: install j dependencies (console) 12 | when: ansible_distribution == "void" 13 | become: yes 14 | xbps: 15 | name: '{{item}}' 16 | with_items: 17 | - libedit 18 | 19 | - name: install j dependencies (x11) 20 | when: ansible_distribution == "void" and use_x11 21 | become: yes 22 | xbps: 23 | name: '{{item}}' 24 | with_items: 25 | - qt5-webkit 26 | - qt5-svg 27 | - qt5-multimedia 28 | - qt5-websockets 29 | 30 | - name: install j 31 | when: ansible_system == "Linux" 32 | get_url: 33 | dest: "{{ansible_env.HOME}}/tmp/j807_linux64.tar.gz" 34 | url: http://www.jsoftware.com/download/j807/install/j807_linux64.tar.gz 35 | sha256sum: f4b27b6f8cf8ccb2da122fc6898df1f121d7fd25c81917258edbf0909aa3f87f 36 | 37 | - name: unpack j 38 | when: ansible_system == "Linux" 39 | unarchive: 40 | src: "{{ansible_env.HOME}}/tmp/j807_linux64.tar.gz" 41 | dest: "{{ansible_env.HOME}}/bin/" 42 | creates: "{{ansible_env.HOME}}/bin/j64-807/bin/jconsole" 43 | 44 | # this is needed by jconsole, it looks like it's assuming 45 | # the .so version used in debian, but the actual version is 20180525-3.1... 46 | - name: symlink libedit to libedit.so.2 47 | when: ansible_distribution == "void" 48 | become: yes 49 | file: 50 | src: /usr/lib/libedit.so.0 51 | dest: /usr/lib/libedit.so.2 52 | state: link 53 | -------------------------------------------------------------------------------- /roles/k/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install kona 4 | become: yes 5 | when: ansible_distribution == "void" 6 | xbps: 7 | name: kona 8 | state: latest 9 | -------------------------------------------------------------------------------- /roles/laptop/files/X1C6_S3_DSDT.patch: -------------------------------------------------------------------------------- 1 | --- dsdt.dsl 2018-03-03 14:47:12.279105691 +0100 2 | +++ dsdt.dsl 2018-03-03 14:26:30.606427931 +0100 3 | @@ -18,9 +18,8 @@ 4 | * Compiler ID "INTL" 5 | * Compiler Version 0x20160527 (538314023) 6 | */ 7 | -DefinitionBlock ("", "DSDT", 2, "LENOVO", "SKL ", 0x00000000) 8 | +DefinitionBlock ("", "DSDT", 2, "LENOVO", "SKL ", 0x00000001) 9 | { 10 | - External (_GPE.TBNF, MethodObj) // 0 Arguments 11 | External (_PR_.BGIA, UnknownObj) 12 | External (_PR_.BGMA, UnknownObj) 13 | External (_PR_.BGMS, UnknownObj) 14 | @@ -40,19 +39,15 @@ 15 | External (_PR_.PDTS, UnknownObj) 16 | External (_PR_.PKGA, UnknownObj) 17 | External (_PR_.POWS, UnknownObj) 18 | - External (_PR_.PR00, DeviceObj) 19 | External (_PR_.PR00.LPSS, PkgObj) 20 | External (_PR_.PR00.TPSS, PkgObj) 21 | External (_PR_.TRPD, UnknownObj) 22 | External (_PR_.TRPF, UnknownObj) 23 | - External (_SB_.GGIV, MethodObj) // 1 Arguments 24 | - External (_SB_.GGOV, MethodObj) // 1 Arguments 25 | External (_SB_.IETM, DeviceObj) 26 | External (_SB_.IETM.DPTE, UnknownObj) 27 | External (_SB_.PCI0.B0D4.NPCC, PkgObj) 28 | External (_SB_.PCI0.CTCD, MethodObj) // 0 Arguments 29 | External (_SB_.PCI0.CTCN, MethodObj) // 0 Arguments 30 | - External (_SB_.PCI0.GFX0, DeviceObj) 31 | External (_SB_.PCI0.GFX0.AINT, MethodObj) // 2 Arguments 32 | External (_SB_.PCI0.GFX0.ALSI, UnknownObj) 33 | External (_SB_.PCI0.GFX0.CBLV, UnknownObj) 34 | @@ -71,109 +66,81 @@ 35 | External (_SB_.PCI0.HDAS.PS3X, MethodObj) // 0 Arguments 36 | External (_SB_.PCI0.HIDW, MethodObj) // 4 Arguments 37 | External (_SB_.PCI0.HIWC, MethodObj) // 1 Arguments 38 | - External (_SB_.PCI0.ISP0, DeviceObj) 39 | - External (_SB_.PCI0.LPCB.EC__.HKEY.DYTC, MethodObj) // 1 Arguments 40 | External (_SB_.PCI0.LPCB.H_EC.XDAT, MethodObj) // 0 Arguments 41 | External (_SB_.PCI0.PAUD.PUAM, MethodObj) // 0 Arguments 42 | - External (_SB_.PCI0.PEG0, DeviceObj) 43 | - External (_SB_.PCI0.PEG0.PEGP, DeviceObj) 44 | External (_SB_.PCI0.PEG0.PG00.PEGP, DeviceObj) 45 | - External (_SB_.PCI0.PEG1, DeviceObj) 46 | External (_SB_.PCI0.PEG1.PG01.PEGP, DeviceObj) 47 | - External (_SB_.PCI0.PEG2, DeviceObj) 48 | External (_SB_.PCI0.PEG2.PG02.PEGP, DeviceObj) 49 | External (_SB_.PCI0.PTDP, UnknownObj) 50 | External (_SB_.PCI0.RP01.PON_, MethodObj) // 0 Arguments 51 | - External (_SB_.PCI0.RP01.PXSX, DeviceObj) 52 | - External (_SB_.PCI0.RP01.PXSX.WGST, MethodObj) // 0 Arguments 53 | - External (_SB_.PCI0.RP01.PXSX.WIST, MethodObj) // 0 Arguments 54 | External (_SB_.PCI0.RP02.PON_, MethodObj) // 0 Arguments 55 | - External (_SB_.PCI0.RP02.PXSX, DeviceObj) 56 | External (_SB_.PCI0.RP02.PXSX.WGST, MethodObj) // 0 Arguments 57 | External (_SB_.PCI0.RP02.PXSX.WIST, MethodObj) // 0 Arguments 58 | External (_SB_.PCI0.RP03.PON_, MethodObj) // 0 Arguments 59 | - External (_SB_.PCI0.RP03.PXSX, DeviceObj) 60 | External (_SB_.PCI0.RP03.PXSX.WGST, MethodObj) // 0 Arguments 61 | External (_SB_.PCI0.RP03.PXSX.WIST, MethodObj) // 0 Arguments 62 | External (_SB_.PCI0.RP04.PON_, MethodObj) // 0 Arguments 63 | - External (_SB_.PCI0.RP04.PXSX, DeviceObj) 64 | External (_SB_.PCI0.RP04.PXSX.WGST, MethodObj) // 0 Arguments 65 | External (_SB_.PCI0.RP04.PXSX.WIST, MethodObj) // 0 Arguments 66 | External (_SB_.PCI0.RP05.PON_, MethodObj) // 0 Arguments 67 | External (_SB_.PCI0.RP05.PWRG, UnknownObj) 68 | - External (_SB_.PCI0.RP05.PXSX, DeviceObj) 69 | External (_SB_.PCI0.RP05.PXSX.WGST, MethodObj) // 0 Arguments 70 | External (_SB_.PCI0.RP05.PXSX.WIST, MethodObj) // 0 Arguments 71 | External (_SB_.PCI0.RP05.RSTG, UnknownObj) 72 | External (_SB_.PCI0.RP05.SCLK, UnknownObj) 73 | External (_SB_.PCI0.RP06.PON_, MethodObj) // 0 Arguments 74 | - External (_SB_.PCI0.RP06.PXSX, DeviceObj) 75 | External (_SB_.PCI0.RP06.PXSX.WGST, MethodObj) // 0 Arguments 76 | External (_SB_.PCI0.RP06.PXSX.WIST, MethodObj) // 0 Arguments 77 | External (_SB_.PCI0.RP07.PON_, MethodObj) // 0 Arguments 78 | - External (_SB_.PCI0.RP07.PXSX, DeviceObj) 79 | External (_SB_.PCI0.RP07.PXSX.WGST, MethodObj) // 0 Arguments 80 | External (_SB_.PCI0.RP07.PXSX.WIST, MethodObj) // 0 Arguments 81 | External (_SB_.PCI0.RP08.PON_, MethodObj) // 0 Arguments 82 | - External (_SB_.PCI0.RP08.PXSX, DeviceObj) 83 | External (_SB_.PCI0.RP08.PXSX.WGST, MethodObj) // 0 Arguments 84 | External (_SB_.PCI0.RP08.PXSX.WIST, MethodObj) // 0 Arguments 85 | External (_SB_.PCI0.RP09.PEGP.NVST, MethodObj) // 0 Arguments 86 | External (_SB_.PCI0.RP09.PON_, MethodObj) // 0 Arguments 87 | External (_SB_.PCI0.RP09.PWRG, UnknownObj) 88 | - External (_SB_.PCI0.RP09.PXSX, DeviceObj) 89 | External (_SB_.PCI0.RP09.PXSX.WGST, MethodObj) // 0 Arguments 90 | External (_SB_.PCI0.RP09.PXSX.WIST, MethodObj) // 0 Arguments 91 | External (_SB_.PCI0.RP09.RSTG, UnknownObj) 92 | External (_SB_.PCI0.RP09.SCLK, UnknownObj) 93 | External (_SB_.PCI0.RP10.PON_, MethodObj) // 0 Arguments 94 | - External (_SB_.PCI0.RP10.PXSX, DeviceObj) 95 | External (_SB_.PCI0.RP10.PXSX.WGST, MethodObj) // 0 Arguments 96 | External (_SB_.PCI0.RP10.PXSX.WIST, MethodObj) // 0 Arguments 97 | External (_SB_.PCI0.RP11.PON_, MethodObj) // 0 Arguments 98 | - External (_SB_.PCI0.RP11.PXSX, DeviceObj) 99 | External (_SB_.PCI0.RP11.PXSX.WGST, MethodObj) // 0 Arguments 100 | External (_SB_.PCI0.RP11.PXSX.WIST, MethodObj) // 0 Arguments 101 | External (_SB_.PCI0.RP12.PON_, MethodObj) // 0 Arguments 102 | - External (_SB_.PCI0.RP12.PXSX, DeviceObj) 103 | External (_SB_.PCI0.RP12.PXSX.WGST, MethodObj) // 0 Arguments 104 | External (_SB_.PCI0.RP12.PXSX.WIST, MethodObj) // 0 Arguments 105 | External (_SB_.PCI0.RP13.PON_, MethodObj) // 0 Arguments 106 | External (_SB_.PCI0.RP13.PWRG, UnknownObj) 107 | - External (_SB_.PCI0.RP13.PXSX, DeviceObj) 108 | External (_SB_.PCI0.RP13.PXSX.WGST, MethodObj) // 0 Arguments 109 | External (_SB_.PCI0.RP13.PXSX.WIST, MethodObj) // 0 Arguments 110 | External (_SB_.PCI0.RP13.RSTG, UnknownObj) 111 | External (_SB_.PCI0.RP13.SCLK, UnknownObj) 112 | External (_SB_.PCI0.RP14.PON_, MethodObj) // 0 Arguments 113 | - External (_SB_.PCI0.RP14.PXSX, DeviceObj) 114 | External (_SB_.PCI0.RP14.PXSX.WGST, MethodObj) // 0 Arguments 115 | External (_SB_.PCI0.RP14.PXSX.WIST, MethodObj) // 0 Arguments 116 | External (_SB_.PCI0.RP15.PON_, MethodObj) // 0 Arguments 117 | - External (_SB_.PCI0.RP15.PXSX, DeviceObj) 118 | External (_SB_.PCI0.RP15.PXSX.WGST, MethodObj) // 0 Arguments 119 | External (_SB_.PCI0.RP15.PXSX.WIST, MethodObj) // 0 Arguments 120 | External (_SB_.PCI0.RP16.PON_, MethodObj) // 0 Arguments 121 | - External (_SB_.PCI0.RP16.PXSX, DeviceObj) 122 | External (_SB_.PCI0.RP16.PXSX.WGST, MethodObj) // 0 Arguments 123 | External (_SB_.PCI0.RP16.PXSX.WIST, MethodObj) // 0 Arguments 124 | External (_SB_.PCI0.RP17.PON_, MethodObj) // 0 Arguments 125 | External (_SB_.PCI0.RP17.PWRG, UnknownObj) 126 | - External (_SB_.PCI0.RP17.PXSX, DeviceObj) 127 | External (_SB_.PCI0.RP17.PXSX.WGST, MethodObj) // 0 Arguments 128 | External (_SB_.PCI0.RP17.PXSX.WIST, MethodObj) // 0 Arguments 129 | External (_SB_.PCI0.RP17.RSTG, UnknownObj) 130 | External (_SB_.PCI0.RP17.SCLK, UnknownObj) 131 | External (_SB_.PCI0.RP18.PON_, MethodObj) // 0 Arguments 132 | - External (_SB_.PCI0.RP18.PXSX, DeviceObj) 133 | External (_SB_.PCI0.RP18.PXSX.WGST, MethodObj) // 0 Arguments 134 | External (_SB_.PCI0.RP18.PXSX.WIST, MethodObj) // 0 Arguments 135 | External (_SB_.PCI0.RP19.PON_, MethodObj) // 0 Arguments 136 | - External (_SB_.PCI0.RP19.PXSX, DeviceObj) 137 | External (_SB_.PCI0.RP19.PXSX.WGST, MethodObj) // 0 Arguments 138 | External (_SB_.PCI0.RP19.PXSX.WIST, MethodObj) // 0 Arguments 139 | External (_SB_.PCI0.RP20.PON_, MethodObj) // 0 Arguments 140 | - External (_SB_.PCI0.RP20.PXSX, DeviceObj) 141 | External (_SB_.PCI0.RP20.PXSX.WGST, MethodObj) // 0 Arguments 142 | External (_SB_.PCI0.RP20.PXSX.WIST, MethodObj) // 0 Arguments 143 | External (_SB_.PCI0.SAT0.NVM1.VLPM, UnknownObj) 144 | @@ -192,20 +159,15 @@ 145 | External (_SB_.PCI0.XHC_.RHUB.PS0X, MethodObj) // 0 Arguments 146 | External (_SB_.PCI0.XHC_.RHUB.PS2X, MethodObj) // 0 Arguments 147 | External (_SB_.PCI0.XHC_.RHUB.PS3X, MethodObj) // 0 Arguments 148 | - External (_SB_.SGOV, MethodObj) // 2 Arguments 149 | - External (_SB_.TBFP, MethodObj) // 1 Arguments 150 | External (_SB_.TPM_.PTS_, MethodObj) // 1 Arguments 151 | External (_SB_.UBTC.NTFY, MethodObj) // 0 Arguments 152 | External (_TZ_.ETMD, IntObj) 153 | External (_TZ_.TZ00, DeviceObj) 154 | External (_TZ_.TZ01, DeviceObj) 155 | - External (ADBG, MethodObj) // 1 Arguments 156 | External (ALSE, UnknownObj) 157 | - External (BNUM, UnknownObj) 158 | External (BRTL, UnknownObj) 159 | External (CFGD, UnknownObj) 160 | External (DIDX, UnknownObj) 161 | - External (DX2H, MethodObj) // 2 Arguments 162 | External (GSMI, UnknownObj) 163 | External (IGDS, UnknownObj) 164 | External (LHIH, UnknownObj) 165 | @@ -215,29 +177,6 @@ 166 | External (M32L, UnknownObj) 167 | External (M64B, UnknownObj) 168 | External (M64L, UnknownObj) 169 | - External (MBGS, MethodObj) // 1 Arguments 170 | - External (MMRP, MethodObj) // 1 Arguments 171 | - External (MMTB, MethodObj) // 1 Arguments 172 | - External (ODV0, IntObj) 173 | - External (ODV1, IntObj) 174 | - External (ODV2, IntObj) 175 | - External (ODV3, IntObj) 176 | - External (ODV4, IntObj) 177 | - External (ODV5, IntObj) 178 | - External (ODV6, IntObj) 179 | - External (ODV7, IntObj) 180 | - External (ODV8, IntObj) 181 | - External (ODV9, IntObj) 182 | - External (ODVA, IntObj) 183 | - External (ODVB, IntObj) 184 | - External (ODVC, IntObj) 185 | - External (ODVD, IntObj) 186 | - External (ODVE, IntObj) 187 | - External (ODVF, IntObj) 188 | - External (ODVG, IntObj) 189 | - External (ODVH, IntObj) 190 | - External (ODVI, IntObj) 191 | - External (ODVJ, IntObj) 192 | External (PC00, IntObj) 193 | External (PC01, UnknownObj) 194 | External (PC02, UnknownObj) 195 | @@ -256,9 +195,6 @@ 196 | External (PC15, UnknownObj) 197 | External (PTTB, UnknownObj) 198 | External (SGMD, UnknownObj) 199 | - External (STDV, IntObj) 200 | - External (TBTD, MethodObj) // 1 Arguments 201 | - External (TBTF, MethodObj) // 1 Arguments 202 | 203 | Name (MBUF, Buffer (0x4000){}) 204 | OperationRegion (MDBR, SystemMemory, 0xAB52C018, 0x00004008) 205 | @@ -415,9 +351,7 @@ 206 | Name (SS1, 0x00) 207 | Name (SS2, 0x00) 208 | Name (SS3, One) 209 | - One 210 | Name (SS4, One) 211 | - One 212 | OperationRegion (GNVS, SystemMemory, 0x4FF4E000, 0x0771) 213 | Field (GNVS, AnyAcc, Lock, Preserve) 214 | { 215 | @@ -13824,8 +13758,7 @@ 216 | If ((DerefOf (Arg0 [0x00]) == 0x01)) 217 | { 218 | ADBG (Concatenate ("POFF GPIO=", ToHexString (DerefOf (Arg0 [0x02])))) 219 | - \_SB.SGOV (DerefOf (Arg0 [0x02]), (DerefOf (Arg0 [0x03]) ^ 220 | - 0x01)) 221 | + \_SB.SGOV (DerefOf (Arg0 [0x02]), (DerefOf (Arg0 [0x03]) ^ 0x01)) 222 | } 223 | 224 | If ((DerefOf (Arg0 [0x00]) == 0x02)) 225 | @@ -27559,6 +27492,13 @@ 226 | 0x00, 227 | 0x00 228 | }) 229 | + Name (\_S3, Package (0x04) // _S3_: S3 System State 230 | + { 231 | + 0x05, 232 | + 0x05, 233 | + 0x00, 234 | + 0x00 235 | + }) 236 | Name (\_S4, Package (0x04) // _S4_: S4 System State 237 | { 238 | 0x06, 239 | @@ -34795,4 +34735,3 @@ 240 | } 241 | } 242 | } 243 | - 244 | -------------------------------------------------------------------------------- /roles/laptop/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: update grub 4 | when: ansible_distribution == "void" and is_laptop 5 | become: yes 6 | raw: 'update-grub' 7 | 8 | - name: reconfigure kernel 9 | when: ansible_distribution == "void" and is_laptop 10 | become: yes 11 | raw: 'xbps-reconfigure -f linux4.16' 12 | -------------------------------------------------------------------------------- /roles/laptop/tasks/acpi_events.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # The external display connect/disconnect is commented out below because 4 | # automatic disconnecting isn't quite right yet. 5 | - name: add ACPI handlers for various hardware events 6 | when: is_laptop and ansible_distribution == "void" 7 | become: yes 8 | blockinfile: 9 | backup: yes 10 | path: /etc/acpi/handler.sh 11 | insertbefore: ' \*\)' 12 | block: | 13 | button/mute) 14 | case "$2" in 15 | MUTE) 16 | logger "Toggling mute..." 17 | # setting Master mute via toggle seems to set mute 18 | # for the headphones / speaker, but toggling it off 19 | # leaves them muted. Seems to be a known issue. 20 | amixer sset Master toggle | grep "\[on\]" \ 21 | && amixer sset Headphone unmute \ 22 | && amixer sset Speaker unmute;; 23 | *) logger "ACPI action undefined (MUTE): $2" ;; 24 | esac 25 | ;; 26 | button/volumedown) 27 | case "$2" in 28 | VOLDN) 29 | amixer set Master 5\%- ;; 30 | *) logger "ACPI action undefined (VOLDN): $2" ;; 31 | esac 32 | ;; 33 | button/volumeup) 34 | case "$2" in 35 | VOLUP) 36 | amixer set Master 5\%+ ;; 37 | *) logger "ACPI action undefined (VOLUP): $2" ;; 38 | esac 39 | ;; 40 | video/brightnessdown) 41 | case "$2" in 42 | BRTDN) 43 | xbacklight -dec 10 ;; 44 | *) logger "ACPI action undefined (BRTDN): $2" ;; 45 | esac 46 | ;; 47 | video/brightnessup) 48 | case "$2" in 49 | BRTUP) 50 | xbacklight -inc 10 ;; 51 | *) logger "ACPI action undefined (BRTUP): $2" ;; 52 | esac 53 | ;; 54 | # jack/videoout) 55 | # case "$2" in 56 | # VIDEOOUT) 57 | # if [ "$3" = "unplug" ]; then 58 | # logger "Disconnecting external display" 59 | # xrandr --output DP1 --off 60 | # else 61 | # logger "Connecting external display" 62 | # xrandr --output eDP1 --left-of DP1 \ 63 | # && xrandr --output eDP1 --auto \ 64 | # && xrandr --output DP1 --auto 65 | # fi 66 | # ;; 67 | # *) logger "ACPI action undefined (VIDEOOUT): $2" ;; 68 | # esac 69 | # ;; 70 | -------------------------------------------------------------------------------- /roles/laptop/tasks/hardware.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Most of this is based on: 4 | # https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X1_Carbon_(Gen_6) 5 | 6 | # https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X1_Carbon_(Gen_6)#Power_management.2FThrottling_issues 7 | - name: install void laptop power management packages 8 | become: yes 9 | when: ansible_distribution == "void" and is_laptop 10 | xbps: 11 | name: '{{item}}' 12 | state: present 13 | with_items: 14 | - acpi 15 | - acpid 16 | - laptop-mode 17 | - powertop 18 | 19 | - name: enable acpid service 20 | become: yes 21 | when: ansible_distribution == "void" and is_laptop 22 | file: 23 | src: /etc/sv/acpid 24 | dest: /var/service/acpid 25 | state: link 26 | owner: root 27 | group: root 28 | mode: 0770 29 | 30 | ### reset the threshold for CPU overtemp throttling, apparently it's 31 | ### misconfigured on Linux (80 C, rather than 97 C)? 32 | - name: install tool for patching power management 33 | become: yes 34 | when: ansible_distribution == "void" and is_laptop 35 | xbps: 36 | name: msr-tools 37 | state: present 38 | 39 | - name: create cpu-throttling.sh 40 | become: yes 41 | when: ansible_distribution == "void" and is_laptop 42 | blockinfile: 43 | path: /usr/local/bin/cpu-throttling.sh 44 | create: yes 45 | owner: root 46 | group: root 47 | mode: 0770 48 | block: | 49 | #!/bin/bash 50 | /bin/modprobe msr 51 | wrmsr -a 0x1a2 0x3000000 # which sets the offset to 3 C, so the new trip point is 97 C 52 | 53 | - name: ensure minutely root cron dir exists 54 | become: yes 55 | when: ansible_distribution == "void" and is_laptop 56 | file: 57 | path: /root/bin/cron/minutely.d 58 | state: directory 59 | owner: root 60 | group: root 61 | mode: 0770 62 | 63 | - name: symlink cpu-throttling script into minutely 64 | become: yes 65 | file: 66 | src: /usr/local/bin/cpu-throttling.sh 67 | dest: /root/bin/cron/minutely.d/cpu-throttling.sh 68 | owner: root 69 | group: root 70 | state: link 71 | 72 | 73 | # https://gist.github.com/greigdp/bb70fbc331a0aaf447c2d38eacb85b8f 74 | - name: enable GPU power saving 75 | become: yes 76 | when: ansible_distribution == "void" and is_laptop and graphics_card is defined and graphics_card == 'i915' 77 | lineinfile: 78 | create: yes 79 | backup: yes 80 | dest: /etc/modprobe.d/i915.conf 81 | line: 'options i915 modeset=1 enable_rc6=1 enable_fbc=1 enable_guc_loading=1 enable_guc_submission=1 enable_psr=1' 82 | 83 | 84 | ### patching ACPI DSDT, based on https://delta-xi.net/#056 85 | - name: install tools for patching ACPI DSDT 86 | become: yes 87 | when: ansible_distribution == "void" and is_laptop 88 | xbps: 89 | name: '{{item}}' 90 | state: present 91 | with_items: 92 | - cpio 93 | - acpica-utils 94 | 95 | - name: make a dir for DSDT patching 96 | become: yes 97 | file: 98 | path: /tmp/dsdt_patching 99 | state: directory 100 | owner: root 101 | group: wheel 102 | mode: 0770 103 | 104 | ## Now this is locally vendored, since it needed to be modified slightly: 105 | ## the OperationRegion line in the patch file was changed. 106 | # - name: download the X1 carbon gen 6 DSDT patch 107 | # get_url: 108 | # url: https://delta-xi.net/download/X1C6_S3_DSDT.patch 109 | # dest: /tmp/dsdt_patching/X1C6_S3_DSDT.patch 110 | # checksum: sha256:645777cdbe82a516aa2c330f6c45322fc51b094d3e24d5b51737793f96c8669d 111 | 112 | # This is using the `command` module because just using `become: yes` 113 | # with `copy` doesn't appear to work when the local _src_ is unreadable 114 | # without become (i.e., become seems to apply to creating the target, but 115 | # not reading the source). 116 | - name: dump ACPI DSDT 117 | become: yes 118 | when: ansible_distribution == "void" and is_laptop 119 | command: cp /sys/firmware/acpi/tables/DSDT /tmp/dsdt_patching/dsdt.aml 120 | args: 121 | creates: /tmp/dsdt_patching/dsdt.aml 122 | 123 | - name: set ACPI DSDT copy file permissions 124 | become: yes 125 | when: ansible_distribution == "void" and is_laptop 126 | file: 127 | path: /tmp/dsdt_patching/dsdt.aml 128 | owner: root 129 | group: wheel 130 | mode: 0770 131 | 132 | - name: decompile the ACPI DSDT 133 | command: iasl -d dsdt.aml 134 | args: 135 | chdir: /tmp/dsdt_patching 136 | creates: /tmp/dsdt_patching/dsdt.dsl 137 | 138 | - name: check whether the file has been patched already 139 | shell: 'grep "^DefinitionBlock" /tmp/dsdt_patching/dsdt.dsl' 140 | register: grep_dsdt_for_patch 141 | 142 | # The patch module doesn't recognize the message that the patch has 143 | # already been applied, so it's treated as a failure, which keeps 144 | # the patch module from being idempotent. :( 145 | # Known issue: https://github.com/ansible/ansible/issues/32803 146 | - name: apply the ACPI DSDT patch 147 | when: '"0x00000001" not in grep_dsdt_for_patch.stdout' 148 | patch: 149 | backup: yes 150 | basedir: /tmp/dsdt_patching 151 | src: X1C6_S3_DSDT.patch 152 | 153 | - name: recompile the ACPI DSDT 154 | command: iasl -ve -tc -p patched_dsdt dsdt.dsl 155 | args: 156 | chdir: /tmp/dsdt_patching 157 | creates: /tmp/dsdt_patching/patched_dsdt.aml 158 | 159 | - name: make directory for CPIO archive 160 | file: 161 | path: /tmp/dsdt_patching/kernel/firmware/acpi 162 | state: directory 163 | 164 | - name: copy patched DSDT into CPIO archive directory 165 | copy: 166 | src: /tmp/dsdt_patching/patched_dsdt.aml 167 | dest: /tmp/dsdt_patching/kernel/firmware/acpi/dsdt.aml 168 | 169 | - name: build CPIO archive 170 | shell: find kernel | cpio -H newc --create > acpi_override.img 171 | args: 172 | creates: /tmp/dsdt_patching/acpi_override.img 173 | chdir: /tmp/dsdt_patching/ 174 | 175 | - name: copy acpi_override to /boot 176 | become: yes 177 | copy: 178 | src: /tmp/dsdt_patching/acpi_override.img 179 | dest: /boot/acpi_override.img 180 | owner: root 181 | group: root 182 | mode: 0700 183 | 184 | # this doesn't work yet -- this config option is newly supported in grub 185 | # 2.04, and void is currently using 2.02. When this does work, editing 186 | # /etc/grub.d/10_linux with lineinfile below may no longer be necessary. 187 | # For now, ensure it is absent, so the setting isn't applied twice. 188 | - name: add loading the override to grub config via grub options 189 | become: yes 190 | when: ansible_distribution == "void" and is_laptop 191 | lineinfile: 192 | create: yes 193 | backup: yes 194 | dest: /etc/default/grub 195 | state: absent 196 | regexp: '^GRUB_EARLY_INITRD_LINUX_CUSTOM=' 197 | line: 'GRUB_EARLY_INITRD_LINUX_CUSTOM="acpi_override.img"' 198 | notify: 199 | - update grub 200 | 201 | # This ensures that the change will be included when update-grub is run. 202 | - name: add loading the ACPI DSDT override to grub.d 203 | become: yes 204 | when: ansible_distribution == "void" and is_laptop 205 | lineinfile: 206 | create: no 207 | backup: yes 208 | state: present 209 | dest: /etc/grub.d/10_linux 210 | regexp: '^\s*initrd\s.*rel_dirname' 211 | line: ' initrd /boot/acpi_override.img ${rel_dirname}/${initrd}' 212 | notify: 213 | - update grub 214 | 215 | 216 | # https://forums.lenovo.com/t5/Linux-Discussion/X1-Carbon-Gen-6-cannot-enter-deep-sleep-S3-state-aka-Suspend-to/m-p/4056794/highlight/true#M10831 217 | # 218 | # Remove `acpi.ec_no_wakeup=1`: I tried this, and it's an improvement 219 | # (only 10% battery loss in suspend overnight, compared to clearly not 220 | # even sleeping when the laptop lid is closed), but it does not come out 221 | # of suspend when opening the lid -- I need to push the power button to 222 | # wake. Several people recommend just patching the ACPI DSDT instead, and 223 | # having tried both, patching the DSDT works significantly better. 224 | - name: add to deep sleep to grub options 225 | become: yes 226 | when: ansible_distribution == "void" and is_laptop 227 | lineinfile: 228 | create: yes 229 | backup: yes 230 | dest: /etc/default/grub 231 | regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=' 232 | # note: "mem_sleep_default=deep" instead of "acpi.ec_no_wakeup=1" 233 | line: 'GRUB_CMDLINE_LINUX_DEFAULT="loglevel=4 slub_debug=P page_poison=1 mem_sleep_default=deep"' 234 | notify: 235 | - update grub 236 | 237 | - name: ensure dracut is configured to use microcode 238 | become: yes 239 | when: ansible_distribution == "void" and is_laptop 240 | lineinfile: 241 | path: /etc/dracut.conf.d/intel_ucode.conf 242 | create: yes 243 | line: 'early_microcode=yes' 244 | 245 | - name: install intel microcode updates 246 | become: yes 247 | when: ansible_distribution == "void" and is_laptop 248 | xbps: 249 | name: intel-ucode 250 | state: present 251 | notify: 252 | - reconfigure kernel 253 | -------------------------------------------------------------------------------- /roles/laptop/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: hardware.yml 4 | 5 | - include: acpi_events.yml 6 | -------------------------------------------------------------------------------- /roles/lisp/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install lisp/scheme stuff (Void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - chez-scheme 10 | - chicken 11 | - sbcl 12 | -------------------------------------------------------------------------------- /roles/lua/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Lua stuff (Void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - lua 10 | - lua52 11 | - LuaJIT 12 | - luarocks 13 | - luarocks-lua52 14 | - lua-lpeg 15 | - lua-zlib 16 | - luasocket 17 | - luaposix 18 | - luaexpat 19 | - luafilesystem 20 | - luasec 21 | -------------------------------------------------------------------------------- /roles/ocaml/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install OCaml and related tooling (Void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - ocaml 10 | - opam 11 | # these are recommended by opam 12 | - m4 13 | - darcs 14 | -------------------------------------------------------------------------------- /roles/phone/files/90-android-phone-in-plugdev-group.rules: -------------------------------------------------------------------------------- 1 | # USB device "18d1:4ee1 Google Inc. Nexus Device (MTP)" 2 | # get the path from lsusb, e.g. bus 005 device 051 becomes: 3 | # udevadm info -a -p $(udevadm info -q path -n /dev/bus/usb/005/051) 4 | SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4ee1", MODE="0660", GROUP="plugdev" 5 | -------------------------------------------------------------------------------- /roles/phone/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: update udev rules 4 | become: yes 5 | when: ansible_os_family == "void" 6 | command: udevadm control --reload 7 | -------------------------------------------------------------------------------- /roles/phone/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install android file transfer (void) 4 | become: yes 5 | when: ansible_os_family == "void" 6 | xbps: 7 | name: android-file-transfer-linux 8 | state: latest 9 | 10 | - name: install simple-mtpfs (void) 11 | become: yes 12 | when: ansible_os_family == "void" 13 | xbps: 14 | name: simple-mtpfs 15 | state: latest 16 | 17 | - name: ensure plugdev group exists 18 | become: yes 19 | when: ansible_os_family == "void" 20 | group: 21 | name: plugdev 22 | state: present 23 | 24 | - name: ensure user is in plugdev group 25 | become: yes 26 | when: ansible_os_family == "void" 27 | user: 28 | append: yes 29 | groups: plugdev 30 | name: '{{ansible_user_id}}' 31 | 32 | - name: ensure /etc/udev/rules.d exists 33 | become: yes 34 | file: 35 | path: /etc/udev/rules.d 36 | state: directory 37 | owner: root 38 | group: root 39 | mode: 0755 40 | 41 | - name: add a udev rule for android phone 42 | become: yes 43 | when: ansible_os_family == "void" 44 | copy: 45 | src: 90-android-phone-in-plugdev-group.rules 46 | dest: /etc/udev/rules.d/90-android-phone-in-plugdev-group.rules 47 | owner: root 48 | group: root 49 | mode: 0644 50 | notify: 51 | - update udev rules 52 | -------------------------------------------------------------------------------- /roles/prolog/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install prolog and related tooling (void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - swi-prolog 10 | -------------------------------------------------------------------------------- /roles/python/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install python and related tooling (Void) 3 | become: yes 4 | when: ansible_os_family == "void" 5 | xbps: 6 | name: "{{item}}" 7 | state: latest 8 | with_items: 9 | - python-pip 10 | - python-virtualenv 11 | -------------------------------------------------------------------------------- /roles/virtualization/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Note: if the host has been running for a while, building the kernel 4 | # plugins may fail, because an older kernel is being used than still has 5 | # development headers on on disk (or something like that). 6 | # 7 | # In this case, reboot, and then run: 8 | # sudo xbps-reconfigure -f virtualbox-ose-dkms 9 | # to rebuild the kernels. 10 | # 11 | # Also, ensure that VT-x is enabled in the computer's BIOS. 12 | 13 | - name: install vagrant (void) 14 | become: yes 15 | xbps: 16 | name: "{{item}}" 17 | state: present 18 | with_items: 19 | - vagrant 20 | - virtualbox-ose 21 | 22 | - name: ensure user is in vboxusers group 23 | become: yes 24 | when: ansible_os_family == "void" 25 | user: 26 | append: yes 27 | groups: vboxusers 28 | name: '{{ansible_user_id}}' 29 | -------------------------------------------------------------------------------- /roles/void/files/clear-xbps-pkg-cache: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | xbps-remove -O 3 | -------------------------------------------------------------------------------- /roles/void/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install preferred shell 4 | become: yes 5 | when: preferred_shell is defined 6 | xbps: name={{preferred_shell}} state=latest 7 | 8 | - name: ensure user is in wheel group 9 | become: yes 10 | user: 11 | append: yes 12 | groups: wheel 13 | name: '{{ansible_user_id}}' 14 | 15 | 16 | - name: change default shell 17 | become: yes 18 | when: preferred_shell is defined 19 | user: 20 | name: '{{ansible_user_id}}' 21 | shell: /bin/{{preferred_shell}} 22 | 23 | - name: install man pages 24 | become: yes 25 | xbps: 26 | name: '{{item}}' 27 | state: present 28 | with_items: 29 | - man-pages 30 | - man-pages-devel 31 | - man-pages-posix 32 | 33 | # https://wiki.voidlinux.eu/Activating_a_log_daemon 34 | - name: install logging daemon 35 | become: yes 36 | xbps: 37 | name: socklog-void 38 | state: present 39 | 40 | - name: ensure socklog service symlink exists 41 | become: yes 42 | file: 43 | src: "/etc/sv/{{item}}" 44 | dest: "/var/service/{{item}}" 45 | state: link 46 | with_items: 47 | - socklog-unix 48 | - nanoklogd 49 | 50 | - name: ensure user is in socklog group 51 | become: yes 52 | user: 53 | append: yes 54 | groups: socklog 55 | name: '{{ansible_user_id}}' 56 | 57 | - name: enable incoming sshd 58 | become: yes 59 | when: run_sshd is defined and run_sshd 60 | file: 61 | src: /etc/sv/sshd 62 | dest: /var/service/sshd 63 | state: link 64 | owner: root 65 | group: root 66 | mode: 0770 67 | 68 | - name: set console keymap to dvorak 69 | become: yes 70 | lineinfile: 71 | backup: yes 72 | state: present 73 | create: yes 74 | path: /etc/rc.conf 75 | regexp: '^#?KEYMAP=' 76 | line: 'KEYMAP="dvorak ctrl"' 77 | 78 | - name: set hardware clock to UTC 79 | become: yes 80 | lineinfile: 81 | backup: yes 82 | state: present 83 | create: yes 84 | path: /etc/rc.conf 85 | regexp: '^#?HARDWARECLOCK=' 86 | line: 'HARDWARECLOCK=UTC' 87 | 88 | - name: set local timezone 89 | become: yes 90 | lineinfile: 91 | backup: yes 92 | state: present 93 | create: yes 94 | path: /etc/rc.conf 95 | regexp: '^#?TIMEZONE=' 96 | line: 'TIMEZONE={{host_timezone}}' 97 | 98 | - name: set terminal font 99 | become: yes 100 | lineinfile: 101 | backup: yes 102 | state: present 103 | create: yes 104 | path: /etc/rc.conf 105 | regexp: '^#FONT=' 106 | line: 'FONT=ter-v22n' 107 | 108 | - name: install an ntp daemon (OpenNTPD) 109 | become: yes 110 | xbps: 111 | name: openntpd 112 | state: present 113 | 114 | - name: configure OpenNTPD 115 | become: yes 116 | lineinfile: 117 | backup: yes 118 | create: yes 119 | state: present 120 | path: /etc/ntpd.conf 121 | line: 'servers pool.ntp.org' 122 | 123 | - name: enable OpenNTPD service 124 | become: yes 125 | file: 126 | src: /etc/sv/openntpd 127 | dest: /var/service/openntpd 128 | state: link 129 | owner: root 130 | group: root 131 | mode: 0770 132 | 133 | # https://wiki.voidlinux.eu/XBPS#Substituting_the_default_system_repository_with_a_regional_repository 134 | - name: use a closer Void package mirror 135 | become: yes 136 | lineinfile: 137 | backup: yes 138 | create: yes 139 | path: /etc/xbps.d/00-repository-main.conf 140 | state: present 141 | regexp: '^repository=' 142 | # Potsdam, NY; will fall back on default mirror in Germany if 404 143 | line: 'repository=https://mirror.clarkson.edu/voidlinux/current/' 144 | 145 | - name: ensure root weekly cron dir exists 146 | become: yes 147 | file: 148 | path: "/root/bin/cron/weekly.d/" 149 | state: directory 150 | owner: root 151 | group: root 152 | mode: 0700 153 | 154 | - name: periodically clear xbps pkg cache 155 | become: yes 156 | copy: 157 | src: "clear-xbps-pkg-cache" 158 | mode: "0744" 159 | dest: "/root/bin/cron/weekly.d/clear-xbps-pkg-cache" 160 | -------------------------------------------------------------------------------- /roles/wifi/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # using connman / connmanctl for wifi & ethernet management 4 | 5 | # ensure the symlinks for these services are absent 6 | - name: disable dhcpd and wpa_supplicant services 7 | become: yes 8 | when: ansible_distribution == "void" and is_laptop 9 | file: 10 | path: /var/service/{{item}} 11 | state: absent 12 | with_items: 13 | - dhcpcd 14 | - wpa_supplicant 15 | 16 | - name: install connman 17 | become: yes 18 | when: ansible_distribution == "void" and is_laptop 19 | xbps: 20 | name: connman 21 | state: latest 22 | 23 | - name: enable and start services for connman 24 | become: yes 25 | when: ansible_distribution == "void" and is_laptop 26 | file: 27 | src: /etc/sv/{{item}} 28 | path: /var/service/{{item}} 29 | state: link 30 | owner: root 31 | group: root 32 | mode: 0770 33 | with_items: 34 | - dbus 35 | - connmand 36 | 37 | # basic connman usage: 38 | # 39 | # Needs to be run with sudo: 40 | # $ sudo connmanctl 41 | # Turn the wifi on (also valid: disable, for e.g. airplane mode) 42 | # > enable wifi 43 | # Enable a wpa_supplicant agent; PSK networks will fail without this 44 | # > agent on 45 | # Scan for wifi networks (doesn't print them) 46 | # > scan wifi 47 | # Actually print them 48 | # > services 49 | # Connect to a wifi network, with tab completion for the long unique ID. 50 | # This may prompt for a password. 51 | # > connect wifi_ 52 | # > exit 53 | -------------------------------------------------------------------------------- /roles/x11/files/20-keyboard_dvorak.conf: -------------------------------------------------------------------------------- 1 | Section "InputClass" 2 | Identifier "any value works here" 3 | MatchIsKeyboard "on" # Limit these settings to keyboards 4 | # Driver "libinput" 5 | # Keyboard layout - comma-separated list for multiple layouts 6 | #Option "XkbLayout" "en" 7 | # Keyboard variant - comma-separated list matching XkbLayout line 8 | Option "XkbVariant" "dvorak" 9 | EndSection 10 | -------------------------------------------------------------------------------- /roles/x11/tasks/install_web_browsers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install web browsers 4 | become: yes 5 | when: ansible_distribution == "void" 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - chromium 11 | - firefox 12 | - w3m 13 | -------------------------------------------------------------------------------- /roles/x11/tasks/install_x11_void.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: install xorg packages 4 | when: ansible_distribution == "void" 5 | become: yes 6 | xbps: 7 | name: "{{item}}" 8 | state: latest 9 | with_items: 10 | - dmenu 11 | - rxvt-unicode 12 | - spectrwm 13 | - workrave 14 | - xbindkeys 15 | - xorg 16 | - xorg-fonts 17 | - terminus-font 18 | - font-inconsolata-otf 19 | 20 | - name: install other useful x packages 21 | when: ansible_distribution == "void" 22 | become: yes 23 | xbps: 24 | name: "{{item}}" 25 | state: latest 26 | with_items: 27 | - mupdf 28 | - xsel 29 | - xclip 30 | - xvkbd 31 | 32 | - name: set up xorg.conf.d directory 33 | when: ansible_distribution == "void" 34 | become: yes 35 | file: 36 | dest: /etc/X11/xorg.conf.d/ 37 | state: directory 38 | owner: root 39 | group: root 40 | mode: 0755 41 | 42 | - name: set keyboard layout to dvorak 43 | become: yes 44 | copy: 45 | src: 20-keyboard_dvorak.conf 46 | dest: /etc/X11/xorg.conf.d/20-keyboard_dvorak.conf 47 | owner: root 48 | group: root 49 | mode: 0744 50 | 51 | # this will be run via .xinitrc 52 | - name: install dunst notification server 53 | become: yes 54 | xbps: 55 | name: dunst 56 | state: present 57 | -------------------------------------------------------------------------------- /roles/x11/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install x11 stuff 3 | when: ansible_distribution == "void" 4 | include: install_x11_void.yml 5 | 6 | - name: install web browsers 7 | include: install_web_browsers.yml 8 | --------------------------------------------------------------------------------