├── .gitignore
├── LICENSE
├── README.md
├── TODO.md
├── ansible
├── Makefile
├── README.md
├── ansible.cfg
├── inventory.hydra
├── inventory.sample
├── playbook.yml
└── roles
│ ├── bootstrap-node
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── apt.yml
│ │ ├── hostname.yml
│ │ ├── locale.yml
│ │ ├── main.yml
│ │ ├── node-exporter.yml
│ │ ├── ssh.yml
│ │ ├── timezone.yml
│ │ └── user.yml
│ ├── templates
│ │ └── ssh-banner.j2
│ └── vars
│ │ └── main.yml
│ ├── setup-docker
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ │ └── daemon.json
│ ├── setup-tailscale
│ ├── handlers
│ │ └── main.yml
│ └── tasks
│ │ └── main.yml
│ └── viasite-ansible.zsh
│ ├── .gitignore
│ ├── .gitlab-ci.yml
│ ├── .travis.yml
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── Vagrantfile
│ ├── defaults
│ └── main.yml
│ ├── install.sh
│ ├── meta
│ ├── .galaxy_install_info
│ └── main.yml
│ ├── molecule
│ ├── default
│ │ ├── molecule.yml
│ │ └── tests
│ │ │ └── test_default.py
│ ├── resources
│ │ ├── converge.yml
│ │ └── prepare.yml
│ ├── shared
│ │ └── molecule.yml
│ └── user
│ │ ├── molecule.yml
│ │ └── prepare.yml
│ ├── playbook.yml
│ ├── scripts
│ └── generate-changelog
│ ├── tasks
│ ├── configure.yml
│ ├── install.yml
│ ├── main.yml
│ └── post-install.yml
│ ├── templates
│ └── zshrc.j2
│ ├── tests
│ └── vagrant.yml
│ └── vars
│ └── main.yml
├── docs
├── SETUP.md
└── calvin.jpg
├── talks
├── foss-united-apr-2021.html
├── foss-united-apr-2021.md
└── img
│ ├── cycle.jpg
│ ├── isp-monitoring-2.png
│ └── isp-monitoring.png
└── terraform
├── .terraform.lock.hcl
├── Makefile
├── env.sample
├── main.tf
├── modules
├── caddy
│ ├── conf
│ │ ├── Caddyfile-internal
│ │ ├── Caddyfile-public
│ │ └── caddy.nomad
│ ├── data.tf
│ ├── job.tf
│ ├── providers.tf
│ └── variables.tf
├── cloudflare
│ ├── records.tf
│ ├── variables.tf
│ ├── versions.tf
│ └── zones.tf
├── digitalocean
│ ├── README.md
│ ├── firewalls.tf
│ ├── floyd.tf
│ ├── output.tf
│ ├── project.tf
│ ├── ssh.tf
│ └── versions.tf
├── doggo
│ ├── conf
│ │ └── doggo.nomad
│ ├── job.tf
│ └── providers.tf
├── gitea
│ ├── conf
│ │ ├── app.ini.tpl
│ │ └── gitea.nomad
│ ├── data.tf
│ ├── job.tf
│ ├── providers.tf
│ └── variables.tf
├── monitoring
│ ├── conf
│ │ ├── monitoring.nomad
│ │ └── prometheus.yml
│ ├── data.tf
│ ├── job.tf
│ └── providers.tf
├── pihole
│ ├── conf
│ │ └── pihole.nomad
│ ├── job.tf
│ └── providers.tf
├── restic
│ ├── conf
│ │ └── restic.nomad
│ ├── job.tf
│ ├── providers.tf
│ └── variables.tf
├── shynet
│ ├── conf
│ │ ├── app.nomad
│ │ └── db.nomad
│ ├── job.tf
│ ├── providers.tf
│ └── variables.tf
└── syncthing
│ ├── conf
│ └── app.nomad
│ ├── job.tf
│ └── providers.tf
├── providers.tf
├── variables.tf
└── versions.tf
/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant
2 | packer*
3 | www
4 | inventory
5 | *.tfvars
6 | .terraform.tfstate.lock.info
7 | .terraform
8 | *.tfstate
9 | *.tfstate.backup
10 | *.backup
11 | *.env
12 | AdGuardHome.yaml
13 | .ci-vault-pass
14 | consul-keys.txt
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Karan Sharma
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
hydra
5 |
6 | Setup scripts for my homelab
7 |
8 |
9 |
10 |
11 | ---
12 |
13 | ## Overview
14 |
15 | - Single node [Nomad](https://www.nomadproject.io/) server for running workloads.
16 | - [Consul](https://www.consul.io/) agent co-located for service discovery.
17 | - [Ansible](https://www.ansible.com/) scripts to boostrap the node.
18 | - [Terraform](https://www.terraform.io/) modules for managing the following services:
19 | - Nomad jobs
20 | - Cloudflare DNS
21 | - DigitalOcean Infra
22 | - [Tailscale VPN](https://tailscale.com/) for connectivity to internal services.
23 | - [Caddy](https://caddyserver.com/) as a reverse proxy for all web services.
24 |
25 | ## Services Running
26 |
27 | - [Pihole](https://pi-hole.net/)
28 | - [Gitea](https://gitea.io/)
29 | - [Shynet](https://github.com/milesmcc/shynet)
30 | - [Syncthing](https://syncthing.net/)
31 |
32 | ## Blog Posts
33 |
34 | Here's a collection of posts I've written which shows how Hydra has evolved over the years:
35 |
36 | - **2021-02-14**: [Home Server with Nomad](https://mrkaran.dev/posts/home-server-nomad/)
37 | - **2020-04-23**: [Home Server Updates](https://mrkaran.dev/posts/home-server-updates/)
38 | - **2019-09-22**: [Home Server Setup](https://mrkaran.dev/posts/home-server-setup/)
39 |
40 | ## Setup Instructions
41 |
42 | Visit [SETUP.md](./docs/SETUP.md) for following instructions on setting up Nomad and Consul.
43 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | ## Baby Steps
2 |
3 | - [x] Setup Tailscale in Floyd/Gilmour.
4 | - [x] Configure Nomad and Consul to bind on Tailscale Address.
5 | - [x] Deploy Caddy as a Nomad Job which
6 | - [x] binds to 80/443 on host
7 | - [x] mounts the cert directory
8 | - [x] template file (caddy.tpl)
9 | - [x] Configure `nomad.mrkaran.dev` and `consul.mrkaran.dev`.
10 | - [x] Create Terraform module for running workloads as Nomad jobs.
11 |
12 | ## Hands on by deploying more workloads
13 |
14 | - [x] Deploy `shynet.mrkaran.dev`
15 |
--------------------------------------------------------------------------------
/ansible/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: run
2 |
3 | run:
4 | ansible-playbook playbook.yml -i inventory --extra-vars "hosts=hydra"
5 |
--------------------------------------------------------------------------------
/ansible/README.md:
--------------------------------------------------------------------------------
1 | # Ansible Playbook for setting up Hydra Home Server
2 |
3 | ## Running
4 |
5 | ## Imp things to keep in mind
6 |
7 | 1) `ansible_ssh_user` for the first run should `root` since there is no user in the instance.
8 | You must ensure that `bootstrap-nodes` role is first run before continuing. It disables the `root` SSH login to the instance and only
9 | the `username` supplied in `inventory` has access to SSH.
10 |
11 | **Bootstrap**: `ansible-playbook -i inventory playbook.yml --tag=bootstrap`
12 |
13 | If you fail at this step, you need to debug before proceeding.
14 |
15 |
16 | 2) For Tailscale, it is recommended to generate `Pre Authorisation Keys` and encrypt them in vault:
17 |
18 | - To encrypt the string `ansible-vault encrypt_string '' --name 'tailscale_auth_key`
19 | - To run the playbook: `ansible-playbook -i inventory playbook.yml --tag=tailscale --ask-vault-pass`
20 |
--------------------------------------------------------------------------------
/ansible/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | roles_path = ./roles
3 | inventory = ./inventory
4 | # strategy_plugins = /home/karan/.local/lib/python3.8/site-packages/ansible_mitogen/plugins/strategy
5 | # strategy = mitogen_linear
6 | [ssh_connection]
7 | scp_if_ssh = True
--------------------------------------------------------------------------------
/ansible/inventory.hydra:
--------------------------------------------------------------------------------
1 | [hydra:children]
2 | floyd
3 |
4 | [floyd]
5 | floyd ansible_ssh_host=floyd ansible_ssh_user=karan ansible_ssh_port=22 remote_ssh_user=karan
6 |
7 | [floyd:vars]
8 | username=karan
9 | github_ssh_key_url=https://github.com/mr-karan.keys
--------------------------------------------------------------------------------
/ansible/inventory.sample:
--------------------------------------------------------------------------------
1 | [hydra:children]
2 | srv1
3 |
4 | [srv1]
5 | srv1 ansible_ssh_host=srv1 ansible_ssh_user=username ansible_ssh_port=22 remote_ssh_user=user
6 |
7 | [srv1:vars]
8 | username=username
9 | github_ssh_key_url=https://github.com/username.keys
--------------------------------------------------------------------------------
/ansible/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - hosts: all
4 | roles:
5 | - role: bootstrap-node
6 | tags:
7 | - bootstrap
8 |
9 | - role: setup-docker
10 | become: true
11 | tags:
12 | - docker
13 |
14 | - role: setup-tailscale
15 | become: yes
16 | tags:
17 | - tailscale
18 |
19 | - role: viasite-ansible.zsh
20 | become: yes
21 | tags:
22 | - zsh
23 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: restart sshd
2 | service:
3 | name: ssh
4 | state: restarted
5 |
6 | - name: reboot
7 | reboot:
8 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/apt.yml:
--------------------------------------------------------------------------------
1 | - name: Update apt cache and upgrade
2 | become: yes
3 | apt:
4 | update_cache: yes
5 | upgrade: "yes"
6 |
7 | - name: Install dependencies
8 | become: yes
9 | apt:
10 | name: "{{ packages }}"
11 | vars:
12 | packages:
13 | - apt-transport-https
14 | - vim
15 | - curl
16 | - jq
17 | - fzf
18 | - python
19 | - python3-pip
20 | - python-apt
21 | - python3-apt
22 | - gnupg2
23 | - gnupg-agent
24 |
25 | - name: install unattended-upgrades
26 | apt:
27 | name: "unattended-upgrades"
28 | state: present
29 |
30 | - name: Remove useless packages from the cache
31 | become: yes
32 | apt:
33 | autoclean: yes
34 |
35 | - name: Remove dependencies that are no longer required
36 | become: yes
37 | apt:
38 | autoremove: yes
39 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/hostname.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: updating hostname to {{inventory_hostname}} from {{ansible_hostname}}
4 | hostname:
5 | name: "{{inventory_hostname}}"
6 | notify:
7 | - reboot
8 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/locale.yml:
--------------------------------------------------------------------------------
1 | - name: Ensure US locale exists
2 | locale_gen:
3 | name: en_US.UTF-8
4 | state: present
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - import_tasks: apt.yml
4 | tags:
5 | - apt
6 |
7 | - import_tasks: locale.yml
8 | tags:
9 | - locale
10 |
11 | - import_tasks: user.yml
12 | tags:
13 | - user
14 |
15 | - import_tasks: ssh.yml
16 | tags:
17 | - ssh
18 |
19 | - import_tasks: timezone.yml
20 | tags:
21 | - timezone
22 |
23 | - import_tasks: hostname.yml
24 | tags:
25 | - hostname
26 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/node-exporter.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mr-karan/homelab/06653f8f276e53b3ef987d80ce65b7d7e190cdce/ansible/roles/bootstrap-node/tasks/node-exporter.yml
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/ssh.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: disable ssh remote root login
4 | lineinfile:
5 | dest: "{{ ssh_sshd_config }}"
6 | regexp: "^#?PermitRootLogin"
7 | line: "PermitRootLogin no"
8 | state: present
9 | notify:
10 | - restart sshd
11 |
12 | - name: enable ssh strict mode
13 | lineinfile:
14 | dest: "{{ ssh_sshd_config }}"
15 | regexp: "^#?StrictModes"
16 | line: "StrictModes yes"
17 | state: present
18 | notify:
19 | - restart sshd
20 |
21 | - name: disable X11 forwarding
22 | lineinfile:
23 | dest: "{{ ssh_sshd_config }}"
24 | regexp: "^#?X11Forwarding"
25 | line: "X11Forwarding no"
26 | state: present
27 | notify:
28 | - restart sshd
29 |
30 | - name: disable ssh password login
31 | lineinfile:
32 | dest: "{{ ssh_sshd_config }}"
33 | regexp: "{{ item.regexp }}"
34 | line: "{{ item.line }}"
35 | state: present
36 | with_items:
37 | - regexp: "^#?PasswordAuthentication"
38 | line: "PasswordAuthentication no"
39 | - regexp: "^#?ChallengeResponseAuthentication"
40 | line: "ChallengeResponseAuthentication no"
41 | - regexp: "^#?PermitEmptyPasswords"
42 | line: "PermitEmptyPasswords no"
43 | notify:
44 | - restart sshd
45 |
46 | - name: set ssh allowed users to {{ username }}
47 | lineinfile:
48 | dest: "{{ ssh_sshd_config }}"
49 | regexp: "^#?AllowUsers"
50 | line: "AllowUsers {{ username }}"
51 | notify:
52 | - restart sshd
53 | when: username != None
54 |
55 | - name: add ssh banner info
56 | lineinfile:
57 | dest: "{{ ssh_sshd_config }}"
58 | regexp: "^#?Banner"
59 | line: "Banner /etc/issue.net"
60 | state: present
61 | notify:
62 | - restart sshd
63 |
64 | - name: update ssh banner
65 | template:
66 | src: ssh-banner.j2
67 | dest: /etc/issue.net
68 | notify:
69 | - restart sshd
70 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/timezone.yml:
--------------------------------------------------------------------------------
1 | - name: Set timezone to Asia/Kolkata
2 | timezone:
3 | name: Asia/Kolkata
4 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/tasks/user.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Make sure we have a 'wheel' group
4 | group:
5 | name: wheel
6 | state: present
7 |
8 | - name: Allow 'wheel' group to have passwordless sudo
9 | lineinfile:
10 | dest: /etc/sudoers
11 | state: present
12 | regexp: '^%wheel'
13 | line: '%wheel ALL=(ALL) NOPASSWD: ALL'
14 | validate: 'visudo -cf %s'
15 | when: ansible_user == "root"
16 |
17 | - name: Add user to wheel group
18 | user:
19 | name: "{{username}}"
20 | groups:
21 | - wheel
22 | append: yes
23 | state: present
24 | createhome: yes
25 | shell: /bin/bash
26 | when: ansible_user == "root"
27 |
28 | - name: Set authorized key for user
29 | authorized_key:
30 | user: "{{username}}"
31 | state: present
32 | key: "{{github_ssh_key_url}}"
33 | when: github_ssh_key_url != None
34 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/templates/ssh-banner.j2:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | * Welcome to {{ansible_hostname}}! The Hydra HomeLab Server. *
3 | * *
4 | * This system is for the use of authorized users only. Usage of *
5 | * this system may be monitored and recorded by system personnel. *
6 | * *
7 | ********************************************************************************
8 |
9 |
--------------------------------------------------------------------------------
/ansible/roles/bootstrap-node/vars/main.yml:
--------------------------------------------------------------------------------
1 | ssh_sshd_config: "/etc/ssh/sshd_config"
2 |
--------------------------------------------------------------------------------
/ansible/roles/setup-docker/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: Start docker on boot
2 | systemd:
3 | name: docker
4 | state: started
5 | enabled: yes
6 |
7 | - name: Restart Docker
8 | systemd:
9 | name: docker
10 | state: restarted
11 |
--------------------------------------------------------------------------------
/ansible/roles/setup-docker/tasks/main.yml:
--------------------------------------------------------------------------------
1 | # sudo apt-get install *
2 | - name: Install docker packages
3 | apt:
4 | name:
5 | [
6 | "apt-transport-https",
7 | "ca-certificates",
8 | "curl",
9 | "gnupg-agent",
10 | "software-properties-common",
11 | ]
12 | state: present
13 | update_cache: yes
14 | tags:
15 | - docker
16 |
17 | # curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
18 | - name: Add Docker s official GPG key
19 | apt_key:
20 | url: https://download.docker.com/linux/ubuntu/gpg
21 | state: present
22 | tags:
23 | - docker
24 |
25 | # sudo apt-key fingerprint 0EBFCD88
26 | - name: Verify that we have the key with the fingerprint
27 | apt_key:
28 | id: 0EBFCD88
29 | state: present
30 | tags:
31 | - docker
32 |
33 | # sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
34 | - name: Set up the stable repository
35 | apt_repository:
36 | repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable
37 | state: present
38 | update_cache: yes
39 | tags:
40 | - docker
41 |
42 | # sudo apt-get update
43 | - name: Update apt packages
44 | apt:
45 | update_cache: yes
46 | tags:
47 | - docker
48 |
49 | # sudo apt-get install docker-ce
50 | - name: Install docker
51 | apt:
52 | state: present
53 | update_cache: yes
54 | name: ["docker-ce", "docker-ce-cli", "containerd.io"]
55 | notify: Start docker on boot
56 | tags:
57 | - docker
58 |
59 | # sudo groupadd docker
60 | - name: Create "docker" group
61 | group:
62 | name: "docker"
63 | state: present
64 | tags:
65 | - docker
66 |
67 | # sudo usermod -aG docker
68 | - name: Add remote user to "docker" group
69 | user:
70 | name: "{{username}}"
71 | group: "docker"
72 | append: yes
73 | tags:
74 | - docker
75 |
76 | - name: Configure sane defaults for logging (docker daemon)
77 | template:
78 | src: "daemon.json"
79 | dest: "/etc/docker/daemon.json"
80 | owner: "root"
81 | group: "root"
82 | mode: "0644"
83 | notify: Restart Docker
84 | tags:
85 | - docker
86 |
87 | - name: Install Docker-compose
88 | shell: sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
89 | tags:
90 | - docker
91 |
92 | - name: Changing perm of /usr/local/bin/docker-compose
93 | file: dest=/usr/local/bin/docker-compose mode=a+x
94 | tags:
95 | - docker
96 |
--------------------------------------------------------------------------------
/ansible/roles/setup-docker/templates/daemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "log-driver": "json-file",
3 | "log-opts": {
4 | "max-size": "10m",
5 | "max-file": "10"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/ansible/roles/setup-tailscale/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: enable tailscaled service
2 | service:
3 | name: tailscaled
4 | state: started
5 | enabled: yes
6 |
7 | - name: Tailscale Status
8 | listen: Confirm Tailscale is Connected
9 | command: tailscale status
10 | register: handlers_tailscale_status
11 |
12 | - name: Assert Tailscale is Connected
13 | listen: Confirm Tailscale is Connected
14 | assert:
15 | that:
16 | - handlers_tailscale_status.stdout | length != 0
17 |
--------------------------------------------------------------------------------
/ansible/roles/setup-tailscale/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: Update apt cache and upgrade
2 | apt:
3 | update_cache: yes
4 | upgrade: "yes"
5 |
6 | - name: Tailscale Signing Key
7 | apt_key:
8 | url: https://pkgs.tailscale.com/stable/{{ ansible_distribution | lower }}/{{ ansible_distribution_release | lower }}.gpg
9 | state: present
10 |
11 | - name: Add Tailscale Deb
12 | apt_repository:
13 | repo: deb https://pkgs.tailscale.com/stable/{{ ansible_distribution | lower }} {{ ansible_distribution_release | lower }} main
14 | state: present
15 |
16 | - name: Install Tailscale
17 | apt:
18 | name: tailscale
19 | state: present
20 | update_cache: yes
21 | notify: enable tailscaled service
22 |
23 | - name: Check if Tailscale is connected
24 | command: tailscale status
25 | changed_when: false
26 | register: tailscale_status
27 |
28 | # - name: Bring Tailscale Up
29 | # become: yes
30 | # command: tailscale up --authkey={{ tailscale_auth_key }}
31 | # register: tailscale_start
32 | # when: tailscale_status.stdout | length == 0
33 | # notify: Confirm Tailscale is Connected
34 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/.gitignore:
--------------------------------------------------------------------------------
1 | .molecule
2 | 00aptproxy
3 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | ---
2 | test:
3 | script:
4 | - molecule test --all
5 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: python
3 | python: "2.7"
4 | sudo: required
5 | services:
6 | - docker
7 |
8 | before_install:
9 | - docker --version
10 | install:
11 | - pip install molecule docker
12 | script:
13 | - molecule test --all
14 |
15 | notifications:
16 | webhooks: https://galaxy.ansible.com/api/v1/notifications/
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [master](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.6...v) (2020-05-01)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * configurable zsh_fzf_path variable and change $HOME/.bin to $HOME/bin ([5b9ab7a](https://github.com/viasite-ansible/ansible-role-zsh/commit/5b9ab7a))
7 | * extending of PATH not just rewrite ([6c2fdd7](https://github.com/viasite-ansible/ansible-role-zsh/commit/6c2fdd7)), closes [#14](https://github.com/viasite-ansible/ansible-role-zsh/issues/14)
8 |
9 |
10 | ### Features
11 |
12 | * fzf path should be /usr/local/bin only in shared scenarios, otherwise it should be installed in local user home ([e3ada98](https://github.com/viasite-ansible/ansible-role-zsh/commit/e3ada98))
13 |
14 |
15 |
16 | ## [3.2.5](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.4...v3.2.5) (2019-03-14)
17 |
18 |
19 | ### Bug Fixes
20 |
21 | * check commands in in check mode ([030bc1f](https://github.com/viasite-ansible/ansible-role-zsh/commit/030bc1f)), closes [#31](https://github.com/viasite-ansible/ansible-role-zsh/issues/31)
22 |
23 |
24 |
25 | ## [3.2.4](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.3...v3.2.4) (2019-03-14)
26 |
27 |
28 | ### Bug Fixes
29 |
30 | * correct run in check mode ([9f6d88b](https://github.com/viasite-ansible/ansible-role-zsh/commit/9f6d88b)), closes [#31](https://github.com/viasite-ansible/ansible-role-zsh/issues/31)
31 |
32 |
33 |
34 | ## [3.2.3](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.2...v3.2.3) (2018-11-21)
35 |
36 |
37 | ### Bug Fixes
38 |
39 | * add POWERLEVEL9K_CONTEXT_REMOTE colors same as POWERLEVEL9K_CONTEXT_DEFAULT ([6794785](https://github.com/viasite-ansible/ansible-role-zsh/commit/6794785))
40 | * don't use paths like ~user in config ([40150ec](https://github.com/viasite-ansible/ansible-role-zsh/commit/40150ec))
41 | * freeze zdharma/fast-syntax-highlighting at v1.2 ([1765bff](https://github.com/viasite-ansible/ansible-role-zsh/commit/1765bff))
42 | * unquote path ([3677d78](https://github.com/viasite-ansible/ansible-role-zsh/commit/3677d78))
43 |
44 |
45 | ### Features
46 |
47 | * shared installation for many users, zsh_shared ([0bdba8e](https://github.com/viasite-ansible/ansible-role-zsh/commit/0bdba8e))
48 | * zsh_aliases ([2770ec3](https://github.com/viasite-ansible/ansible-role-zsh/commit/2770ec3))
49 |
50 |
51 |
52 | ## [3.2.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.1...v3.2.2) (2018-06-13)
53 |
54 |
55 | ### Bug Fixes
56 |
57 | * upgrade fzf 0.17.3 -> 0.17.4 ([98a0569](https://github.com/viasite-ansible/ansible-role-zsh/commit/98a0569))
58 |
59 |
60 |
61 | ## [3.2.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.2.0...v3.2.1) (2018-05-01)
62 |
63 |
64 | ### Features
65 |
66 | * Midnight Commander Solarized Dark skin ([0017e34](https://github.com/viasite-ansible/ansible-role-zsh/commit/0017e34))
67 |
68 |
69 |
70 | # [3.2.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.1.2...v3.2.0) (2018-01-11)
71 |
72 |
73 | ### Bug Fixes
74 |
75 | * alias 'suser' ([ba34e57](https://github.com/viasite-ansible/ansible-role-zsh/commit/ba34e57))
76 | * update fzf to 0.6.11 ([385dc9d](https://github.com/viasite-ansible/ansible-role-zsh/commit/385dc9d))
77 | * upgrade fzf 0.16.11 -> 0.17.3 ([1a08ef2](https://github.com/viasite-ansible/ansible-role-zsh/commit/1a08ef2))
78 |
79 |
80 | ### Features
81 |
82 | * install.sh for current user ([a7c998e](https://github.com/viasite-ansible/ansible-role-zsh/commit/a7c998e))
83 |
84 |
85 |
86 | ## [3.1.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.1.1...v3.1.2) (2017-06-21)
87 |
88 |
89 | ### Features
90 |
91 | * add viasite-ansible/zsh-ansible-server bundle ([3c990b2](https://github.com/viasite-ansible/ansible-role-zsh/commit/3c990b2))
92 |
93 |
94 |
95 | ## [3.1.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.1.0...v3.1.1) (2017-06-14)
96 |
97 |
98 | ### Bug Fixes
99 |
100 | * update fzf to 0.16.8 ([0e7b913](https://github.com/viasite-ansible/ansible-role-zsh/commit/0e7b913))
101 |
102 |
103 | ### Features
104 |
105 | * add systemd bundle ([40c34d0](https://github.com/viasite-ansible/ansible-role-zsh/commit/40c34d0))
106 |
107 |
108 |
109 | # [3.1.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.0.3...v3.1.0) (2017-05-27)
110 |
111 |
112 | ### Features
113 |
114 | * add github-*, fzf-insert-* widgets (ytet5uy4/fzf-widgets update) ([23a7e9c](https://github.com/viasite-ansible/ansible-role-zsh/commit/23a7e9c))
115 |
116 |
117 |
118 | ## [3.0.3](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.0.2...v3.0.3) (2017-05-27)
119 |
120 |
121 | ### Bug Fixes
122 |
123 | * update ytet5uy4/fzf-widgets@3f6b9cf ([58965f1](https://github.com/viasite-ansible/ansible-role-zsh/commit/58965f1))
124 |
125 |
126 |
127 | ## [3.0.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.0.1...v3.0.2) (2017-05-26)
128 |
129 |
130 | ### Bug Fixes
131 |
132 | * switch antigen branch from develop to master ([6141a02](https://github.com/viasite-ansible/ansible-role-zsh/commit/6141a02))
133 |
134 |
135 | ### Features
136 |
137 | * disable zsh share history (unsetopt share_history) ([de0b5ae](https://github.com/viasite-ansible/ansible-role-zsh/commit/de0b5ae)), closes [#16](https://github.com/viasite-ansible/ansible-role-zsh/issues/16)
138 |
139 |
140 |
141 | ## [3.0.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v3.0.0...v3.0.1) (2017-05-14)
142 |
143 |
144 | ### Bug Fixes
145 |
146 | * idempotence and correct `antigen reset` ([44bd345](https://github.com/viasite-ansible/ansible-role-zsh/commit/44bd345))
147 |
148 |
149 | ### Features
150 |
151 | * upgrade to antigen v2 ([a85cc77](https://github.com/viasite-ansible/ansible-role-zsh/commit/a85cc77)), closes [#12](https://github.com/viasite-ansible/ansible-role-zsh/issues/12)
152 |
153 |
154 |
155 | ## [2.1.8](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.7...v2.1.8) (2017-05-13)
156 |
157 |
158 | ### Bug Fixes
159 |
160 | * make working command conditions on clean centos ([71399b8](https://github.com/viasite-ansible/ansible-role-zsh/commit/71399b8)), closes [#8](https://github.com/viasite-ansible/ansible-role-zsh/issues/8)
161 |
162 |
163 |
164 | ## [2.1.7](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.6...v2.1.7) (2017-05-13)
165 |
166 |
167 | ### Bug Fixes
168 |
169 | * replace popstas/zsh-command-time to native powerlevel9k segment ([24e3480](https://github.com/viasite-ansible/ansible-role-zsh/commit/24e3480)), closes [#13](https://github.com/viasite-ansible/ansible-role-zsh/issues/13)
170 |
171 |
172 | ### Features
173 |
174 | * hide host and/or user on local machine (powerlevel9k 0.6 feature) ([12630d4](https://github.com/viasite-ansible/ansible-role-zsh/commit/12630d4)), closes [#15](https://github.com/viasite-ansible/ansible-role-zsh/issues/15)
175 |
176 |
177 |
178 | ## [2.1.6](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.5...v2.1.6) (2017-04-26)
179 |
180 |
181 | ### Bug Fixes
182 |
183 | * skip early compinit execute on Ubuntu ([f581c7b](https://github.com/viasite-ansible/ansible-role-zsh/commit/f581c7b)), closes [#9](https://github.com/viasite-ansible/ansible-role-zsh/issues/9)
184 |
185 |
186 | ### Features
187 |
188 | * add docker widgets from updated ytet5uy4/fzf-widgets ([ee84bf3](https://github.com/viasite-ansible/ansible-role-zsh/commit/ee84bf3))
189 |
190 |
191 |
192 | ## [2.1.5](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.4...v2.1.5) (2017-04-25)
193 |
194 |
195 | ### Bug Fixes
196 |
197 | * make condition for disable command-not-found for macOS ([d789633](https://github.com/viasite-ansible/ansible-role-zsh/commit/d789633)), closes [#7](https://github.com/viasite-ansible/ansible-role-zsh/issues/7)
198 |
199 |
200 |
201 | ## [2.1.4](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.3...v2.1.4) (2017-04-23)
202 |
203 |
204 | ### Bug Fixes
205 |
206 | * support check `command` exists for zsh_antigen_bundles_extras ([b6e4284](https://github.com/viasite-ansible/ansible-role-zsh/commit/b6e4284))
207 |
208 |
209 | ### Features
210 |
211 | * add fzf-kill-process to ytet5uy4/fzf-widgets ([8bc9e93](https://github.com/viasite-ansible/ansible-role-zsh/commit/8bc9e93))
212 | * add viasite/drall, viasite/server-scripts bundles ([74d3451](https://github.com/viasite-ansible/ansible-role-zsh/commit/74d3451))
213 |
214 |
215 |
216 | ## [2.1.3](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.2...v2.1.3) (2017-04-21)
217 |
218 |
219 | ### Features
220 |
221 | * add viasite/drupal-scripts bundle for drs ([7371bde](https://github.com/viasite-ansible/ansible-role-zsh/commit/7371bde))
222 |
223 |
224 |
225 | ## [2.1.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.1...v2.1.2) (2017-04-19)
226 |
227 |
228 | ### Bug Fixes
229 |
230 | * removed debian plugin from zsh_antigen_bundles ([ddb600e](https://github.com/viasite-ansible/ansible-role-zsh/commit/ddb600e)), closes [#6](https://github.com/viasite-ansible/ansible-role-zsh/issues/6)
231 |
232 |
233 |
234 | ## [2.1.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.1.0...v2.1.1) (2017-04-16)
235 |
236 |
237 | ### Bug Fixes
238 |
239 | * HIST_STAMPS, COMPLETION_WAITING_DOTS don't work if it before antigen apply ([4093191](https://github.com/viasite-ansible/ansible-role-zsh/commit/4093191))
240 | * provision role for root on macOS ([2d1f939](https://github.com/viasite-ansible/ansible-role-zsh/commit/2d1f939))
241 |
242 |
243 | ### Features
244 |
245 | * zsh-users/zsh-syntax-highlighting -> zdharma/fast-syntax-highlighting ([ff3542f](https://github.com/viasite-ansible/ansible-role-zsh/commit/ff3542f))
246 |
247 |
248 |
249 | # [2.1.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.0.4...v2.1.0) (2017-04-08)
250 |
251 |
252 | ### Bug Fixes
253 |
254 | * role broken on 'Check commands exists' when skipped ([0676934](https://github.com/viasite-ansible/ansible-role-zsh/commit/0676934))
255 |
256 |
257 | ### Features
258 |
259 | * new widget: fzf-git-delete-branches, add --exact to insert-history ([15d22a4](https://github.com/viasite-ansible/ansible-role-zsh/commit/15d22a4)), closes [ytet5uy4/fzf-widgets#2](https://github.com/ytet5uy4/fzf-widgets/issues/2)
260 |
261 |
262 |
263 | ## [2.0.4](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.0.3...v2.0.4) (2017-04-03)
264 |
265 |
266 | ### Bug Fixes
267 |
268 | * hotkeys with bundle dependency don't enabled if bundle was dict ([4187981](https://github.com/viasite-ansible/ansible-role-zsh/commit/4187981))
269 |
270 |
271 | ### Features
272 |
273 | * add copy-earlier-word to widgets ([ec4382b](https://github.com/viasite-ansible/ansible-role-zsh/commit/ec4382b))
274 | * zsh_hotkeys_extras variable for custom hotkeys ([e7e8b25](https://github.com/viasite-ansible/ansible-role-zsh/commit/e7e8b25))
275 |
276 |
277 |
278 | ## [2.0.3](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.0.2...v2.0.3) (2017-04-03)
279 |
280 |
281 | ### Bug Fixes
282 |
283 | * add debian jessie to platforms ([995c601](https://github.com/viasite-ansible/ansible-role-zsh/commit/995c601))
284 | * move TERM var above theme, for zsh 4.3 ([7030837](https://github.com/viasite-ansible/ansible-role-zsh/commit/7030837))
285 | * zsh, disable autosuggestions for zsh 4.3 ([76521c9](https://github.com/viasite-ansible/ansible-role-zsh/commit/76521c9))
286 |
287 |
288 |
289 | ## [2.0.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.0.1...v2.0.2) (2017-04-02)
290 |
291 |
292 | ### Bug Fixes
293 |
294 | * fzf install for macOS ([ce924e6](https://github.com/viasite-ansible/ansible-role-zsh/commit/ce924e6))
295 | * remove composer plugin from defaults ([7dd8aa3](https://github.com/viasite-ansible/ansible-role-zsh/commit/7dd8aa3))
296 | * zsh-syntax-highlighting loaded on zsh 4.3.10 ([6062c8d](https://github.com/viasite-ansible/ansible-role-zsh/commit/6062c8d))
297 |
298 |
299 |
300 | ## [2.0.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v2.0.0...v2.0.1) (2017-04-02)
301 |
302 |
303 | ### Bug Fixes
304 |
305 | * remove zsh_check_commands, now it calculates dynamically ([84c36ca](https://github.com/viasite-ansible/ansible-role-zsh/commit/84c36ca))
306 |
307 |
308 | ### Features
309 |
310 | * zsh_antigen_bundles_extras for custom bundles ([0e2ac6a](https://github.com/viasite-ansible/ansible-role-zsh/commit/0e2ac6a)), closes [#5](https://github.com/viasite-ansible/ansible-role-zsh/issues/5)
311 |
312 |
313 |
314 | # [2.0.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.6...v2.0.0) (2017-04-02)
315 |
316 |
317 | ### Bug Fixes
318 |
319 | * change antigen version to `master` for idempotency ([dee73e8](https://github.com/viasite-ansible/ansible-role-zsh/commit/dee73e8))
320 | * check for fzf installed any way ([d5f8aae](https://github.com/viasite-ansible/ansible-role-zsh/commit/d5f8aae))
321 | * don't install tmux if plugin enabled, but enable plugin if tmux installed ([640ab24](https://github.com/viasite-ansible/ansible-role-zsh/commit/640ab24))
322 | * install.sh tested on ubuntu and debian ([bcb9112](https://github.com/viasite-ansible/ansible-role-zsh/commit/bcb9112))
323 | * merge install-* files, use `package` module ([a2f89b9](https://github.com/viasite-ansible/ansible-role-zsh/commit/a2f89b9))
324 | * powerlevel9k correct load on zsh 4.3 ([ce2f629](https://github.com/viasite-ansible/ansible-role-zsh/commit/ce2f629))
325 | * white color in phpstorm solarized dark terminal ([422f99c](https://github.com/viasite-ansible/ansible-role-zsh/commit/422f99c))
326 |
327 |
328 | ### Features
329 |
330 | * add naive RedHat support ([102080b](https://github.com/viasite-ansible/ansible-role-zsh/commit/102080b))
331 | * antigen plugin manager ([80f4eab](https://github.com/viasite-ansible/ansible-role-zsh/commit/80f4eab))
332 | * junegunn/fzf replaced with more functional ytet5uy4/fzf-widgets ([ffd2d6e](https://github.com/viasite-ansible/ansible-role-zsh/commit/ffd2d6e))
333 | * load plugin only if command exists in system or if custom `when` is true ([e9288c2](https://github.com/viasite-ansible/ansible-role-zsh/commit/e9288c2)), closes [#2](https://github.com/viasite-ansible/ansible-role-zsh/issues/2)
334 | * zero-knowledge install.sh, docs ([d145b59](https://github.com/viasite-ansible/ansible-role-zsh/commit/d145b59))
335 | * zsh_hotkeys with bundle dependency ([cbacc3d](https://github.com/viasite-ansible/ansible-role-zsh/commit/cbacc3d)), closes [#4](https://github.com/viasite-ansible/ansible-role-zsh/issues/4)
336 |
337 |
338 |
339 | ## [1.1.5](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.4...v1.1.5) (2017-03-09)
340 |
341 |
342 | ### Bug Fixes
343 |
344 | * backup .zshrc ([81e5650](https://github.com/viasite-ansible/ansible-role-zsh/commit/81e5650))
345 |
346 |
347 |
348 | ## [1.1.4](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.3...v1.1.4) (2017-03-08)
349 |
350 |
351 | ### Features
352 |
353 | * zsh_autosuggestions_bind_key_2 ([368fb68](https://github.com/viasite-ansible/ansible-role-zsh/commit/368fb68))
354 |
355 |
356 |
357 | ## [1.1.3](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.2...v1.1.3) (2017-03-08)
358 |
359 |
360 | ### Bug Fixes
361 |
362 | * vcs color foreground black on any color scheme ([2d0d102](https://github.com/viasite-ansible/ansible-role-zsh/commit/2d0d102))
363 |
364 |
365 |
366 | ## [1.1.2](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.1...v1.1.2) (2017-03-06)
367 |
368 |
369 | ### Bug Fixes
370 |
371 | * cannot bind to an empty key sequence for 'zsh_autosuggestions_bind_key' ([94074fa](https://github.com/viasite-ansible/ansible-role-zsh/commit/94074fa))
372 | * idempotence when update git from root to user ([092dbcc](https://github.com/viasite-ansible/ansible-role-zsh/commit/092dbcc))
373 | * macos permissions ([232c0a9](https://github.com/viasite-ansible/ansible-role-zsh/commit/232c0a9))
374 | * remove zsh-highlighting on --tags configure ([802fcba](https://github.com/viasite-ansible/ansible-role-zsh/commit/802fcba))
375 |
376 |
377 |
378 | ## [1.1.1](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.1.0...v1.1.1) (2017-03-05)
379 |
380 |
381 | ### Bug Fixes
382 |
383 | * workaround for zsh-users/zsh-syntax-highlighting[#286](https://github.com/viasite-ansible/ansible-role-zsh/issues/286) ([372633b](https://github.com/viasite-ansible/ansible-role-zsh/commit/372633b))
384 |
385 |
386 |
387 | # [1.1.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/v1.0.0...v1.1.0) (2017-03-05)
388 |
389 |
390 | ### Bug Fixes
391 |
392 | * transfer ownership from popstas to viasite ([b898fe0](https://github.com/viasite-ansible/ansible-role-zsh/commit/b898fe0))
393 |
394 |
395 | ### Features
396 |
397 | * rewrite: switch to powerlevel9k and per user files ([9ef2300](https://github.com/viasite-ansible/ansible-role-zsh/commit/9ef2300))
398 | * rewrite: switch to powerlevel9k and per user files ([69ddc67](https://github.com/viasite-ansible/ansible-role-zsh/commit/69ddc67))
399 | * rewrite: switch to powerlevel9k and per user files ([fa99913](https://github.com/viasite-ansible/ansible-role-zsh/commit/fa99913))
400 |
401 |
402 |
403 | # [1.0.0](https://github.com/viasite-ansible/ansible-role-zsh/compare/1c12b96...v1.0.0) (2017-02-23)
404 |
405 |
406 | ### Bug Fixes
407 |
408 | * setup other user than ansible_remote_user ([1c12b96](https://github.com/viasite-ansible/ansible-role-zsh/commit/1c12b96))
409 |
410 |
411 |
412 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/viasite-ansible/ansible-role-zsh)
2 |
3 | Tested on Debian 10, Ubuntu 16.04, Ubuntu 18.04, Ubuntu 20.04, macOS 10.12, CentOS 8.
4 |
5 | **For upgrade from viasite-ansible.zsh 1.x, 2.x to 3.0 see [below](#upgrade).**
6 |
7 |
8 |
9 | ## Zero-knowledge install:
10 | If you using Ubuntu or Debian and not familiar with Ansible, you can just execute [install.sh](install.sh) on target machine:
11 | ```
12 | curl https://raw.githubusercontent.com/viasite-ansible/ansible-role-zsh/master/install.sh | bash
13 | ```
14 | It will install pip3, ansible and setup zsh for root and current user.
15 |
16 | Then [configure terminal application](#configure-terminal-application).
17 |
18 |
19 | ## Includes:
20 | - zsh
21 | - [antigen](https://github.com/zsh-users/antigen)
22 | - [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh)
23 | - [powerlevel9k theme](https://github.com/bhilburn/powerlevel9k)
24 | - [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)
25 | - [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)
26 | - [unixorn/autoupdate-antigen.zshplugin](https://github.com/unixorn/autoupdate-antigen.zshplugin)
27 | - [ytet5uy4/fzf-widgets](https://github.com/ytet5uy4/fzf-widgets)
28 | - [urbainvaes/fzf-marks](https://github.com/popstas/urbainvaes/fzf-marks)
29 |
30 | ## Features
31 | - customize powerlevel9k theme prompt segments and colors
32 | - default colors tested with solarized dark and default grey terminal in putty
33 | - add custom prompt elements from yml
34 | - custom zsh config with `~/.zshrc.local` or `/etc/zshrc.local`
35 | - load `/etc/profile.d` scripts
36 | - install only plugins that useful for your machine. For example, plugin `docker` will not install if you have not Docker
37 |
38 | ## 1.5 mins demo
39 | 
40 |
41 | ## Color schemes
42 | 
43 |
44 | ## Midnight Commander Solarized Dark skin
45 | If you using Solarized Dark scheme and `mc`, you should want to install skin, then set `zsh_mc_solarized_skin: yes`
46 |
47 |
48 | ## Demo install in Vagrant
49 | You can test work of role before install in real machine.
50 | Just execute `vagrant up`, then `vagrant ssh` for enter in virtual machine.
51 |
52 | Note: you cannot install vagrant on VPS like Digital Ocean or in Docker. Use local machine for it.
53 | [Download](https://www.vagrantup.com/downloads.html) and install vagrant for your operating system.
54 |
55 |
56 |
57 | ## Install for real machine
58 | Zero-knowledge install: see [above](#zero-knowledge-install).
59 |
60 | ### Manual install
61 |
62 | 0. [Install Ansible](http://docs.ansible.com/ansible/intro_installation.html).
63 | For Ubuntu:
64 | ``` bash
65 | sudo apt update
66 | sudo apt install python3-pip -y
67 | sudo pip3 install ansible
68 | ```
69 |
70 | 1. Download role:
71 | ```
72 | ansible-galaxy install viasite-ansible.zsh --force
73 | ```
74 |
75 | 2. Write playbook or use [playbook.yml](playbook.yml):
76 | ```
77 | - hosts: all
78 | vars:
79 | zsh_antigen_bundles_extras:
80 | - nvm
81 | - joel-porquet/zsh-dircolors-solarized
82 | zsh_autosuggestions_bind_key: "^U"
83 | roles:
84 | - viasite-ansible.zsh
85 | ```
86 |
87 | 3. Provision playbook:
88 | ```
89 | ansible-playbook -i "localhost," -c local -K playbook.yml
90 | ```
91 |
92 | If you want to provision role for root user on macOS, you should install packages manually:
93 | ```
94 | brew install zsh git wget
95 | ```
96 |
97 | It will install zsh environment for ansible remote user. If you want to setup zsh for other users,
98 | you should define variable `zsh_user`:
99 |
100 | Via playbook:
101 | ```
102 | - hosts: all
103 | roles:
104 | - { role: viasite-ansible.zsh, zsh_user: otheruser }
105 | - { role: viasite-ansible.zsh, zsh_user: thirduser }
106 | ```
107 |
108 | Or via command:
109 | ```
110 | ansible-playbook -i hosts zsh.yml -e zsh_user=otheruser
111 | ```
112 |
113 | 4. Install fzf **without shell extensions**, [download binary](https://github.com/junegunn/fzf-bin/releases)
114 | or `brew install fzf` for macOS.
115 |
116 | Note: I don't use `tmux-fzf` and don't tested work of it.
117 |
118 |
119 |
120 | ## Multiuser shared install
121 | If you have 10+ users on host, probably you don't want manage tens of configurations and thousands of files.
122 |
123 | In this case you can deploy single zsh config and include it to all users.
124 |
125 | It causes some limitations:
126 |
127 | - Users have read only access to zsh config
128 | - Users cannot disable global enabled bundles
129 | - Possible bugs such cache write permission denied
130 | - Possible bugs with oh-my-zsh themes
131 |
132 | For install shared configuration you should set `zsh_shared: yes`.
133 | Configuration will install to `/usr/share/zsh-config`, then you just can include to user config:
134 |
135 | ``` bash
136 | source /usr/share/zsh-config/.zshrc
137 | ```
138 |
139 | You can still provision custom configs for several users.
140 |
141 |
142 |
143 | ## Configure
144 | You should not edit `~/.zshrc`!
145 | Add your custom config to `~/.zshrc.local` (per user) or `/etc/zshrc.local` (global).
146 | `.zshrc.local` will never touched by ansible.
147 |
148 |
149 | ### Configure terminal application
150 | 1. Download [powerline fonts](https://github.com/powerline/fonts), install font that you prefer.
151 | You can see screenshots [here](https://github.com/powerline/fonts/blob/master/samples/All.md).
152 |
153 | 2. Set color scheme.
154 |
155 | Personaly, I prefer Solarized Dark color sceme, Droid Sans Mono for Powerline in iTerm and DejaVu Sans Mono in Putty.
156 |
157 | #### iTerm
158 | Profiles - Text - Change Font - select font "for Powerline"
159 |
160 | Profiles - Colors - Color Presets... - select Solarized Dark
161 |
162 | #### Putty
163 | Settings - Window - Appearance - Font settings
164 |
165 | You can download [Solarized Dark for Putty](https://github.com/altercation/solarized/tree/master/putty-colors-solarized).
166 |
167 | #### Gnome Terminal
168 | gnome-terminal have built-in Solarized Dark, note that you should select both background color scheme and palette scheme.
169 |
170 |
171 |
172 | ### Hotkeys
173 | You can view hotkeys in [defaults/main.yml](defaults/main.yml), `zsh_hotkeys`.
174 |
175 | Sample hotkey definitions:
176 | ``` yaml
177 | - { hotkey: '^r', action: 'fzf-history' }
178 | # with dependency of bundle
179 | - { hotkey: '`', action: autosuggest-accept, bundle: zsh-users/zsh-autosuggestions }
180 | ```
181 |
182 | Useful to set `autosuggest-accept` to ` hotkey, but it conflicts with Midnight Commander (break Ctrl+O subshell).
183 |
184 | You can add your custom hotkeys without replace default hotkeys with `zsh_hotkeys_extras` variable:
185 | ``` yaml
186 | zsh_hotkeys_extras:
187 | - { hotkey: '^[^[[D', action: backward-word } # alt+left
188 | - { hotkey: '^[^[[C', action: forward-word } # alt+right
189 | # Example inserts 2nd argument from end of prev. cmd
190 | - { hotkey: '^[,', action: copy-earlier-word } # ctrl+,
191 | ```
192 |
193 | ### Aliases
194 | You can use aliases for your command with easy deploy.
195 | Aliases config mostly same as hotkeys config:
196 |
197 | ``` yaml
198 | zsh_aliases:
199 | - { alias: 'dfh', action: 'df -h | grep -v docker' }
200 | # with dependency of bundle and without replace default asiases
201 | - zsh_aliases_extra
202 | - { alias: 'dfh', action: 'df -h | grep -v docker', bundle: }
203 | ```
204 |
205 | #### Default hotkeys from plugins:
206 | - → - accept autosuggestion
207 | - Ctrl+Z - move current application to background, press again for return to foreground
208 | - Ctrl+G - jump to bookmarked directory. Use `mark` in directory for add to bookmarks
209 | - Ctrl+R - show command history
210 | - Ctrl+@ - show all fzf-widgets
211 | - Ctrl+@,C - fzf-change-dir, press fast!
212 | - Ctrl+\\ - fzf-change-recent-dir
213 | - Ctrl+@,G - fzf-change-repository
214 | - Ctrl+@,F - fzf-edit-files
215 | - Ctrl+@,. - fzf-edit-dotfiles
216 | - Ctrl+@,S - fzf-exec-ssh (using your ~/.ssh/config)
217 | - Ctrl+@,G,A - fzf-git-add-file
218 | - Ctrl+@,G,B - fzf-git-checkout-branch
219 | - Ctrl+@,G,D - fzf-git-delete-branches
220 |
221 |
222 |
223 | ## Configure bundles
224 | You can check default bundles in [defaults/main.yml](defaults/main.yml#L37).
225 | If you like default bundles, but you want to add your bundles, use `zsh_antigen_bundles_extras` variable (see example playbook above).
226 | If you want to remove some default bundles, you should use `zsh_antigen_bundles` variable.
227 |
228 | Format of list matches [antigen](https://github.com/zsh-users/antigen#antigen-bundle). All bellow variants valid:
229 | ``` yaml
230 | - docker # oh-my-zsh plugin
231 | - zsh-users/zsh-autosuggestions # plugin from github
232 | - zsh-users/zsh-autosuggestions@v0.3.3 # plugin from github with fixed version
233 | - ~/projects/zsh/my-plugin --no-local-clone # plugin from local directory
234 | ```
235 |
236 | Note that bundles can use conditions for load. There are two types of conditions:
237 |
238 | 1. Command conditions. Just add `command` to bundle:
239 | ``` yaml
240 | - { name: docker, command: docker }
241 | - name: docker-compose
242 | command: docker-compose
243 | ```
244 | Bundles `docker` and `docker-compose` will be added to config only if commands exists on target system.
245 |
246 | 2. When conditions. You can define any ansible conditions as you define in `when` in tasks:
247 | ``` yaml
248 | # load only for zsh >= 4.3.17
249 | - name: zsh-users/zsh-syntax-highlighting
250 | when: "{{ zsh_version is version_compare('4.3.17', '>=') }}"
251 | # load only for macOS
252 | - { name: brew, when: "{{ ansible_os_family != 'Darwin' }}" }
253 | ```
254 | Note: you should wrap condition in `"{{ }}"`
255 |
256 |
257 |
258 | ## Upgrade
259 | viasite-ansible.zsh v3.0 introduces antigen v2.0, it don't have backward compatibility to antigen 1.x.
260 |
261 | I don't spent much time for smooth upgrade, therefore you probably should do some manual actions:
262 | if powerlevel9k prompt don't loaded after provision role, you should execute `antigen reset`.
263 |
264 | After reopen shell all should be done.
265 |
266 | ### Downgrade to antigen v1
267 | Antigen v2 much faster (up to 2x more faster startup), but if something went wrong, you can downgrade to antigen v1,
268 | see note for zsh 4.3 users below.
269 |
270 | ### For users with zsh 4.x
271 | Antigen v2 not work on zsh < 5.0, if you use zsh 4.x, please add to you playbook:
272 | ``` yaml
273 | zsh_antigen_version: v1.4.1
274 | ```
275 |
276 |
277 | ## Known bugs
278 | ### `su username` caused errors
279 | See [antigen issue](https://github.com/zsh-users/antigen/issues/136).
280 | If both root and su user using antigen, you should use `su - username` in place of `su username`.
281 |
282 | Or you can use bundled alias `suser`.
283 |
284 | Also, you can try to fix it, add to `~/.zshrc.local`:
285 | ```
286 | alias su='su -'
287 | ```
288 | But this alias can break you scripts, that using `su`.
289 |
290 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/Vagrantfile:
--------------------------------------------------------------------------------
1 | $VM_BOX = 'bento/ubuntu-16.04'
2 |
3 | Vagrant.configure('2') do |config|
4 | config.vm.box = $VM_BOX
5 |
6 | config.vm.provision "ansible" do |ansible|
7 | ansible.extra_vars = { ansible_ssh_user: 'vagrant', vagrant: true, zsh_user: 'vagrant' }
8 | ansible.sudo = true
9 | ansible.playbook = 'tests/vagrant.yml'
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | zsh_user: "{{ ansible_user_id }}"
4 |
5 | # .zshrc config
6 | zsh_hist_stamps: yyyy-mm-dd
7 | zsh_share_history: no
8 | zsh_update_interval: 30 # set 0 for disable autoupdates
9 | zsh_editor: vim
10 | zsh_term: xterm-256color
11 | zsh_mc_solarized_skin: no
12 |
13 | zsh_path:
14 | - "{{ zsh_fzf_path }}"
15 | - /usr/local/sbin
16 | - /usr/local/bin
17 | - /usr/sbin
18 | - /usr/bin
19 | - /sbin
20 | - /bin
21 | - /usr/games
22 | - /usr/local/games
23 |
24 | zsh_load_etc_profile: yes
25 |
26 | fzf_widgets: ytet5uy4/fzf-widgets
27 |
28 | zsh_antigen_version: master
29 | zsh_fzf_version: 0.17.4
30 |
31 | zsh_antigen_bundles:
32 | - { name: command-not-found, when: "{{ ansible_os_family != 'Darwin' }}" } # too slow on OSX
33 | - { name: brew, command: brew }
34 | - { name: docker, command: docker }
35 | - { name: docker-compose, command: docker-compose }
36 | - fancy-ctrl-z
37 | - git-extras
38 | - gnu-utils
39 | - { name: httpie, command: http }
40 | - { name: golang, command: go }
41 | - { name: gulp, command: gulp }
42 | - { name: helm, command: helm }
43 | - { name: kubectl, command: kubectl }
44 | - { name: pip, command: pip }
45 | - { name: rake, command: rake }
46 | - { name: symfony2, command: symfony }
47 | - { name: systemd, command: systemctl }
48 | - python
49 | - { name: tmux, command: tmux }
50 | - { name: vagrant, command: vagrant }
51 | - { name: viasite/drall, command: drall }
52 | - { name: viasite/drupal-scripts, command: drs }
53 | - { name: viasite/server-scripts, command: dbdump }
54 | - { name: viasite-ansible/zsh-ansible-server, command: ansible-deploy }
55 | - zsh_reload
56 |
57 | # on zsh 4.3.10 autosuggestions breaks multiline commands with \
58 | - { name: zsh-users/zsh-autosuggestions, when: "{{ zsh_version is version_compare('5.0', '>=') }}" }
59 | - popstas/zsh-command-time
60 | - { name: unixorn/autoupdate-antigen.zshplugin, when: "{{ zsh_update_interval > 0 }}" }
61 | - urbainvaes/fzf-marks # replaces jump plugin, mark, jump and Ctrl+G
62 | - "{{ fzf_widgets }}"
63 | # must be last, don't work on zsh < 4.3.17
64 | #- { name: zsh-users/zsh-syntax-highlighting, when: "{{ zsh_version | default(false) is version_compare('4.3.17', '>=') }}" }
65 | # bug with text paste in fast-syntax-highlighting v1.21, see https://github.com/zdharma/fast-syntax-highlighting/issues/30
66 | - { name: zdharma/fast-syntax-highlighting@v1.2, when: "{{ zsh_version is version_compare('4.3.17', '>=') }}" }
67 |
68 | zsh_antigen_bundles_extras: []
69 |
70 | # useful for deploy many zsh users at host, without duplicate and without write access
71 | zsh_shared: no
72 | zsh_change_user_shell: yes
73 |
74 | zsh_antigen_theme: "bhilburn/powerlevel9k powerlevel9k"
75 |
76 | zsh_hotkeys:
77 | # home & end keys work
78 | - { hotkey: '\e[1~', action: beginning-of-line }
79 | - { hotkey: '\e[4~', action: end-of-line }
80 |
81 | # fzf-widgets
82 | - { hotkey: '^@' , action: fzf-select-widget, bundle: "{{ fzf_widgets }}" }
83 | - { hotkey: '^@.' , action: fzf-edit-dotfiles, bundle: "{{ fzf_widgets }}" }
84 | - { hotkey: '^@c', action: fzf-change-directory, bundle: "{{ fzf_widgets }}" }
85 | - { hotkey: '^@f', action: fzf-edit-files, bundle: "{{ fzf_widgets }}" }
86 | - { hotkey: '^@k', action: fzf-kill-processes, bundle: "{{ fzf_widgets }}" }
87 | - { hotkey: '^@s', action: fzf-exec-ssh, bundle: "{{ fzf_widgets }}" }
88 | - { hotkey: '^\' , action: fzf-change-recent-directory, bundle: "{{ fzf_widgets }}" }
89 | - { hotkey: '^r', action: fzf-insert-history, bundle: "{{ fzf_widgets }}" }
90 | - { hotkey: '^xf', action: fzf-insert-files, bundle: "{{ fzf_widgets }}" }
91 | - { hotkey: '^xd', action: fzf-insert-directory, bundle: "{{ fzf_widgets }}" }
92 |
93 | # fzf-widgets: Git
94 | - { hotkey: '^@g', action: fzf-select-git-widget, bundle: "{{ fzf_widgets }}" }
95 | - { hotkey: '^@ga', action: fzf-git-add-files, bundle: "{{ fzf_widgets }}" }
96 | - { hotkey: '^@gc', action: fzf-git-change-repository, bundle: "{{ fzf_widgets }}" }
97 | - { hotkey: '^@gco', action: fzf-git-checkout-branch, bundle: "{{ fzf_widgets }}" }
98 | - { hotkey: '^@gd', action: fzf-git-delete-branches, bundle: "{{ fzf_widgets }}" }
99 |
100 | # fzf-widgets: GitHub
101 | - { hotkey: '^@gh', action: fzf-select-github-widget, bundle: "{{ fzf_widgets }}" }
102 | - { hotkey: '^@ghi', action: fzf-github-show-issue, bundle: "{{ fzf_widgets }}" }
103 | - { hotkey: '^@ghe', action: fzf-github-edit-issue, bundle: "{{ fzf_widgets }}" }
104 | - { hotkey: '^@gho', action: fzf-github-open-issue, bundle: "{{ fzf_widgets }}" }
105 | - { hotkey: '^@ghc', action: fzf-github-close-issue, bundle: "{{ fzf_widgets }}" }
106 | - { hotkey: '^@ghco', action: fzf-github-comment-issue, bundle: "{{ fzf_widgets }}" }
107 |
108 | # fzf-widgets: Docker
109 | - { hotkey: '^@d', action: fzf-select-docker-widget, bundle: "{{ fzf_widgets }}" }
110 | - { hotkey: '^@dk', action: fzf-docker-kill-containers, bundle: "{{ fzf_widgets }}" }
111 | - { hotkey: '^@dl', action: fzf-docker-logs-container, bundle: "{{ fzf_widgets }}" }
112 | - { hotkey: '^@dr', action: fzf-docker-remove-containers, bundle: "{{ fzf_widgets }}" }
113 | - { hotkey: '^@dri', action: fzf-docker-remove-images, bundle: "{{ fzf_widgets }}" }
114 | - { hotkey: '^@drv', action: fzf-docker-remove-volumes, bundle: "{{ fzf_widgets }}" }
115 | - { hotkey: '^@dsa', action: fzf-docker-start-containers, bundle: "{{ fzf_widgets }}" }
116 | - { hotkey: '^@dso', action: fzf-docker-stop-containers, bundle: "{{ fzf_widgets }}" }
117 |
118 | # autosuggestions
119 | - { hotkey: '{{ zsh_autosuggestions_bind_key }}', action: autosuggest-accept, bundle: zsh-users/zsh-autosuggestions }
120 | - { hotkey: '{{ zsh_autosuggestions_bind_key_2 }}', action: autosuggest-accept, bundle: zsh-users/zsh-autosuggestions }
121 |
122 | zsh_hotkeys_extras: []
123 |
124 | # only single quotes allowed in action
125 | zsh_aliases:
126 | - { alias: 'apt-update-list-upgrade', action: 'apt update && apt upgrade --dry-run | grep Inst | sort | fzf && apt upgrade' }
127 | - { alias: 'dfh', action: 'df -h | grep -v docker' }
128 | - { alias: 'ubuntu-release', action: 'lsb_release -a' }
129 | - { alias: '', action: '' }
130 |
131 |
132 | # zsh-autosuggestions
133 | zsh_autosuggestions_max_length: 15
134 | zsh_autosuggestions_bind_key: ""
135 | zsh_autosuggestions_bind_key_2: ""
136 |
137 | # fzf
138 | zsh_fzf_path: "$HOME/bin"
139 | zsh_fzf_height: "100%"
140 | zsh_fzf_reverse: yes
141 | zsh_fzf_border: no
142 | zsh_fzf_ctrl_r_opts: '--exact'
143 |
144 | # command-time
145 | zsh_command_time_min_seconds: 3
146 | zsh_command_time_echo: ""
147 |
148 | # powerlevel9k
149 | zsh_powerlevel9k_left_prompt:
150 | - context
151 | - dir
152 |
153 | zsh_powerlevel9k_right_prompt:
154 | - status
155 | - background_jobs
156 | - vcs
157 | - command_execution_time
158 | - time
159 |
160 | zsh_powerlevel_custom_elements:
161 | - name: command_time
162 | command: "zsh_command_time"
163 | background: "248"
164 | foreground: "000"
165 |
166 | zsh_powerlevel9k_hide_host_on_local: yes
167 | zsh_powerlevel9k_always_show_context: no # hide hostname and username from prompt on local machine
168 | zsh_powerlevel9k_always_show_user: no # hide username from prompt on local machine
169 | zsh_powerlevel9k_prompt_on_newline: no
170 | zsh_powerlevel9k_shorten_dir_length: 3
171 | zsh_powerlevel9k_status_verbose: 0
172 |
173 | # dir (context) colors
174 | zsh_powerlevel9k_context_default_foreground: "255" # white
175 | zsh_powerlevel9k_context_default_background: "024" # blue
176 | zsh_powerlevel9k_context_root_foreground: "255" # white
177 | zsh_powerlevel9k_context_root_background: "124" # red
178 | zsh_powerlevel9k_dir_foreground: "255" # white
179 | zsh_powerlevel9k_dir_background: "240" # gray
180 | zsh_powerlevel9k_dir_etc_foreground: "{{ zsh_powerlevel9k_dir_foreground }}"
181 | zsh_powerlevel9k_dir_etc_background: "{{ zsh_powerlevel9k_dir_background }}"
182 | zsh_powerlevel9k_dir_path_highlight_foreground: "{{ zsh_powerlevel9k_dir_foreground }}"
183 | zsh_powerlevel9k_dir_path_highlight_background: "{{ zsh_powerlevel9k_dir_background }}"
184 |
185 | # vcs colors
186 | zsh_powerlevel9k_vcs_foreground: "232" # about black on any palette
187 | zsh_powerlevel9k_vcs_clean_background: "100" # dirty green
188 | zsh_powerlevel9k_vcs_modified_background: "094" # orange
189 | zsh_powerlevel9k_vcs_untracked_background: "094" # orange
190 |
191 | # command execution time
192 | zsh_powerlevel9k_command_execution_time_foreground: "000"
193 | zsh_powerlevel9k_command_execution_time_background: "248"
194 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -eu
3 |
4 | title() {
5 | local color='\033[1;37m'
6 | local nc='\033[0m'
7 | printf "\n${color}$1${nc}\n"
8 | }
9 |
10 | title "Install pip and Ansible"
11 | sudo apt update
12 | sudo apt install python3-pip -y
13 | sudo pip3 install ansible
14 |
15 | title "Install viasite-ansible.zsh"
16 | ansible-galaxy install viasite-ansible.zsh --force
17 |
18 | title "Download playbook to /tmp/zsh.yml"
19 | curl https://raw.githubusercontent.com/viasite-ansible/ansible-role-zsh/master/playbook.yml > /tmp/zsh.yml
20 |
21 | title "Provision playbook for root"
22 | ansible-playbook -i "localhost," -c local -b /tmp/zsh.yml
23 |
24 | title "Provision playbook for $(whoami)"
25 | ansible-playbook -i "localhost," -c local -b /tmp/zsh.yml --extra-vars="zsh_user=$(whoami)"
26 |
27 | title "Finished! Please, restart your shell."
28 | echo ""
29 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/meta/.galaxy_install_info:
--------------------------------------------------------------------------------
1 | install_date: Mon Feb 8 11:41:50 2021
2 | version: v3.3.2
3 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | author: Stanislav Popov
4 | company: Viasite
5 | description: oh-my-zsh with powerlevel9k theme, fzf and other plugins
6 | license: MIT
7 | min_ansible_version: 2.0
8 | platforms:
9 | - name: Ubuntu
10 | versions:
11 | - trusty
12 | - xenial
13 | - name: Debian
14 | versions:
15 | - squeeze
16 | - wheezy
17 | - jessie
18 | - name: EL
19 | versions:
20 | - 7
21 | - name: MacOSX
22 | versions:
23 | - 10.12
24 | galaxy_tags:
25 | - system
26 | - shell
27 | - user
28 | - zsh
29 | dependencies: []
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/default/molecule.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 | platforms:
5 | - name: ansible-role-zsh-debian-10
6 | image: geerlingguy/docker-debian10-ansible
7 | pre_build_image: true
8 |
9 | - name: ansible-role-zsh-1604
10 | image: geerlingguy/docker-ubuntu1604-ansible
11 | pre_build_image: true
12 |
13 | - name: ansible-role-zsh-1804
14 | image: geerlingguy/docker-ubuntu1804-ansible
15 | pre_build_image: true
16 |
17 | - name: ansible-role-zsh-2004
18 | image: geerlingguy/docker-ubuntu2004-ansible
19 | pre_build_image: true
20 |
21 | - name: ansible-role-zsh-centos-8
22 | image: geerlingguy/docker-centos8-ansible
23 |
24 | #driver:
25 | # name: vagrant
26 | # provider:
27 | # name: virtualbox
28 | #platforms:
29 | # - name: xenial64
30 | # box: bento/ubuntu-16.04
31 |
32 | #verifier:
33 | # name: testinfra
34 |
35 | provisioner:
36 | name: ansible
37 | playbooks:
38 | prepare: ../resources/prepare.yml
39 | converge: ../resources/converge.yml
40 | inventory:
41 | group_vars:
42 | all:
43 | zsh_user: root
44 | zsh_mc_solarized_skin: yes
45 | zsh_antigen_bundles_extras:
46 | - { name: test/in-list, when: true }
47 | - { name: test/not-in-list, when: false }
48 | - { name: test/command-exists, command: zsh }
49 | - { name: test/command-not-exists, command: not-exists-commanddd }
50 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/default/tests/test_default.py:
--------------------------------------------------------------------------------
1 | import os
2 | import testinfra.utils.ansible_runner
3 |
4 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
5 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
6 |
7 |
8 | def test_bundles_when(host):
9 | c = host.file('/root/.zshrc').content
10 | assert 'test/in-list' in c
11 | assert 'test/not-in-list' not in c
12 |
13 |
14 | def test_bundles_command(host):
15 | c = host.file('/root/.zshrc').content
16 | assert 'test/command-exists' in c
17 | assert 'test/command-not-exists' not in c
18 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/resources/converge.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: all
3 | roles:
4 | - ansible-role-zsh
5 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/resources/prepare.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Prepare
3 | hosts: all
4 | gather_facts: False
5 | tasks:
6 | - name: apt-proxy
7 | copy:
8 | content: "Acquire::http::Proxy \"{{ lookup('env', 'APT_PROXY') }}\"; Acquire::https::Proxy \"false\";"
9 | dest: /etc/apt/apt.conf.d/01proxy
10 | failed_when: False
11 | - name: Update apt cache
12 | package:
13 | update_cache: yes
14 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/shared/molecule.yml:
--------------------------------------------------------------------------------
1 | ---
2 | scenario:
3 | name: shared
4 | driver:
5 | name: docker
6 | platforms:
7 | - name: ansible-role-zsh-debian-10
8 | image: geerlingguy/docker-debian10-ansible
9 | pre_build_image: true
10 |
11 | - name: ansible-role-zsh-1604
12 | image: geerlingguy/docker-ubuntu1604-ansible
13 | pre_build_image: true
14 |
15 | - name: ansible-role-zsh-1804
16 | image: geerlingguy/docker-ubuntu1804-ansible
17 | pre_build_image: true
18 |
19 | - name: ansible-role-zsh-2004
20 | image: geerlingguy/docker-ubuntu2004-ansible
21 | pre_build_image: true
22 |
23 | - name: ansible-role-zsh-centos-8
24 | image: geerlingguy/docker-centos8-ansible
25 |
26 | provisioner:
27 | name: ansible
28 | playbooks:
29 | prepare: ../resources/prepare.yml
30 | converge: ../resources/converge.yml
31 | inventory:
32 | group_vars:
33 | all:
34 | zsh_shared: yes
35 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/user/molecule.yml:
--------------------------------------------------------------------------------
1 | ---
2 | scenario:
3 | name: user
4 | driver:
5 | name: docker
6 | platforms:
7 | - name: ansible-role-zsh-debian-10
8 | image: geerlingguy/docker-debian10-ansible
9 | pre_build_image: true
10 |
11 | - name: ansible-role-zsh-1604
12 | image: geerlingguy/docker-ubuntu1604-ansible
13 | pre_build_image: true
14 |
15 | - name: ansible-role-zsh-1804
16 | image: geerlingguy/docker-ubuntu1804-ansible
17 | pre_build_image: true
18 |
19 | - name: ansible-role-zsh-2004
20 | image: geerlingguy/docker-ubuntu2004-ansible
21 | pre_build_image: true
22 |
23 | - name: ansible-role-zsh-centos-8
24 | image: geerlingguy/docker-centos8-ansible
25 |
26 | provisioner:
27 | name: ansible
28 | playbooks:
29 | prepare: prepare.yml
30 | converge: ../resources/converge.yml
31 | inventory:
32 | group_vars:
33 | all:
34 | zsh_user: testuser
35 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/molecule/user/prepare.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Prepare
3 | hosts: all
4 | gather_facts: False
5 | tasks:
6 | - name: apt-proxy
7 | copy:
8 | content: "Acquire::http::Proxy \"{{ lookup('env', 'APT_PROXY') }}\"; Acquire::https::Proxy \"false\";"
9 | dest: /etc/apt/apt.conf.d/01proxy
10 | failed_when: False
11 |
12 | - name: create testuser
13 | user:
14 | name: testuser
15 | home: /home/testuser
16 | shell: /bin/bash
17 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: all
3 | vars:
4 | # your extra bundles here
5 | zsh_antigen_bundles_extras: []
6 | # your variables here
7 | zsh_autosuggestions_bind_key: "^U"
8 | roles:
9 | - viasite-ansible.zsh
10 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/scripts/generate-changelog:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | HELP="
4 | 1. If github branch exists,
5 | rename origin to origin_origin,
6 | rename copy github to origin.
7 |
8 | 2. Generate CHANGELOG.md
9 |
10 | 3. Reverts all branch operations at step 1
11 | "
12 |
13 | IS_BRANCH_RENAME=$(git remote | grep -c github)
14 |
15 | # 1.
16 | if [ "$IS_BRANCH_RENAME" = "1" ]; then
17 | git remote rename origin origin_origin
18 | git remote rename github origin
19 | fi
20 |
21 | # 2.
22 | conventional-changelog -p angular -o CHANGELOG.md -r 0
23 | sed -i.bak 's/# \[\]/# [master]/g' CHANGELOG.md
24 | rm CHANGELOG.md.bak
25 | git add CHANGELOG.md
26 |
27 | # 3.
28 | if [ "$IS_BRANCH_RENAME" = "1" ]; then
29 | git remote rename origin github
30 | git remote rename origin_origin origin
31 | fi
32 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/tasks/configure.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Check zsh version
4 | shell: "set -o pipefail; zsh --version | cut -d ' ' -f2"
5 | args:
6 | executable: /bin/bash
7 | register: zsh_register_version
8 | check_mode: no
9 | changed_when: false
10 | tags: configure
11 |
12 | - name: Set zsh_version variable
13 | set_fact:
14 | zsh_version: "{{ zsh_register_version.stdout }}"
15 |
16 | - name: Merge bundles lists
17 | set_fact:
18 | zsh_antigen_bundles: "{{ zsh_antigen_bundles }} + {{ zsh_antigen_bundles_extras }}"
19 |
20 | - name: Disable autoupdate if zsh_shared install
21 | set_fact:
22 | zsh_update_interval: 0
23 | when: zsh_shared
24 |
25 | - name: Check commands exists
26 | shell: "command -v {{ item.command }} || which {{ item.command }}"
27 | with_items: "{{ zsh_antigen_bundles }}"
28 | failed_when: false
29 | changed_when: false
30 | check_mode: no
31 | when: item.command is defined
32 | register: zsh_register_commands_exists
33 |
34 | - name: Merge hotkeys lists
35 | set_fact:
36 | zsh_hotkeys: "{{ zsh_hotkeys }} + {{ zsh_hotkeys_extras }}"
37 |
38 | - name: Check antigen version
39 | shell: |
40 | set -o pipefail
41 | cat "{{ zsh_antigen_path }}/antigen/VERSION" | tr -d 'v'
42 | args:
43 | executable: /bin/bash
44 | register: zsh_register_antigen_version
45 | changed_when: false
46 | failed_when: false
47 | check_mode: no
48 | tags: configure
49 |
50 | - name: Set zsh_antigen_installed_version variable
51 | set_fact:
52 | zsh_antigen_installed_version: "{{ zsh_register_antigen_version.stdout }}"
53 |
54 | - name: Write .zshrc config
55 | template:
56 | src: zshrc.j2
57 | dest: "{{ zsh_config }}"
58 | owner: "{{ zsh_user }}"
59 | group: "{{ zsh_user_group }}"
60 | backup: yes
61 |
62 | - name: Set zsh as default shell
63 | user:
64 | name: "{{ zsh_user }}"
65 | shell: /bin/zsh
66 | become: true
67 | when: not zsh_shared and zsh_change_user_shell
68 |
69 | - name: Add skip_global_compinit for disable early compinit call in Ubuntu
70 | lineinfile:
71 | regexp: "skip_global_compinit=1"
72 | line: "skip_global_compinit=1"
73 | dest: /etc/zsh/zshenv
74 | state: present
75 | when: ansible_distribution == 'Ubuntu'
76 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/tasks/install.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Update package cache
4 | package:
5 | update_cache: yes
6 | when: ansible_os_family != 'Darwin'
7 |
8 | - name: Install zsh, git, wget
9 | package:
10 | name:
11 | - zsh
12 | - git
13 | - wget
14 | state: present
15 | # brew don't work from root user on macOS
16 | when: not (zsh_user == 'root' and ansible_os_family == 'Darwin')
17 |
18 | - name: Clone antigen {{ zsh_antigen_version }}
19 | git:
20 | repo: https://github.com/zsh-users/antigen.git
21 | dest: "{{ zsh_antigen_path }}/antigen"
22 | version: "{{ zsh_antigen_version }}"
23 | force: yes
24 | become: yes
25 | become_user: "{{ zsh_user }}"
26 | register: zsh_register_antigen_clone
27 |
28 | - name: Clone iwfmp/mc-solarized-skin
29 | git:
30 | repo: https://github.com/iwfmp/mc-solarized-skin.git
31 | version: master
32 | dest: "~{{ zsh_user }}/.mc/lib/mc-solarized"
33 | force: yes
34 | become: yes
35 | become_user: "{{ zsh_user }}"
36 | when: zsh_mc_solarized_skin and not zsh_shared
37 |
38 | - name: Check fzf installed
39 | command: which fzf
40 | changed_when: false
41 | failed_when: false
42 | check_mode: no
43 | register: zsh_register_fzf_command
44 |
45 | - name: Set zsh_fzf_path to /usr/local/bin
46 | set_fact:
47 | zsh_fzf_path: /usr/local/bin
48 | changed_when: false
49 | when: zsh_shared
50 |
51 | - name: Set zsh_fzf_path_absolute
52 | set_fact:
53 | zsh_fzf_path_absolute: "{{ zsh_fzf_path | replace('$HOME', '~' + zsh_user) }}"
54 | changed_when: false
55 |
56 | - name: Ensure users home binary folder is present
57 | file:
58 | path: "{{ zsh_fzf_path_absolute }}"
59 | owner: "{{ zsh_user }}"
60 | group: "{{ zsh_user_group }}"
61 | mode: u=rwx,g=rwx,o=rx
62 | state: directory
63 | when: not zsh_shared
64 |
65 | - name: "Download fzf to {{ zsh_fzf_path_absolute }}"
66 | unarchive:
67 | src: "{{ zsh_fzf_url }}"
68 | dest: "{{ zsh_fzf_path_absolute }}"
69 | remote_src: yes
70 | creates: "{{ zsh_fzf_path_absolute }}/fzf"
71 | when: zsh_register_fzf_command.rc == 1
72 |
73 | - name: Set directory permissions
74 | file:
75 | name: "{{ zsh_antigen_path }}"
76 | owner: "{{ zsh_user }}"
77 | group: "{{ zsh_user_group }}"
78 | recurse: yes
79 | changed_when: false
80 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - include: install.yml
4 | tags: [ zsh, install ]
5 |
6 | - include: configure.yml
7 | tags: [ zsh, configure ]
8 |
9 | - include: post-install.yml
10 | tags: [ zsh, install, post_install ]
11 |
12 | - name: Reset antigen cache
13 | command: "/bin/zsh -c 'source {{ zsh_config }}; antigen reset'"
14 | become: yes
15 | become_user: "{{ zsh_user }}"
16 | changed_when: false
17 | failed_when: false
18 | tags: always
19 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/tasks/post-install.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Reset antigen cache
3 | command: "/bin/zsh -c 'source {{ zsh_config }}; antigen reset'"
4 | become: yes
5 | become_user: "{{ zsh_user }}"
6 | changed_when: false
7 | failed_when: false
8 |
9 | # it will fail, but it install all bundles for user
10 | - name: Update antigen bundles
11 | command: "/bin/zsh -c 'source {{ zsh_config }}; antigen update'"
12 | become: yes
13 | become_user: "{{ zsh_user }}"
14 | changed_when: false
15 | failed_when: false
16 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/templates/zshrc.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 | # zsh version: {{ zsh_version }}
3 | # antigen version: {{ zsh_antigen_installed_version }}
4 |
5 | export TERM="{{ zsh_term }}"
6 | export EDITOR="{{ zsh_editor }}"
7 | export PATH="$PATH:{{ zsh_path | join(":") }}"
8 |
9 | HIST_STAMPS="{{ zsh_hist_stamps }}"
10 | UPDATE_ZSH_DAYS="{{ zsh_update_interval }}"
11 | COMPLETION_WAITING_DOTS="true"
12 |
13 | # ADOTDIR="{{ zsh_antigen_path_compat }}"
14 | {% if zsh_shared %}
15 | ANTIGEN_AUTO_CONFIG=false # disable updates
16 | _ANTIGEN_THEME_COMPAT=false # disable theme cache
17 | {% endif %}
18 |
19 | ANTIGEN_BUNDLES="{{ zsh_antigen_path_compat }}/bundles"
20 | ANTIGEN_PLUGIN_UPDATE_DAYS="{{ zsh_update_interval }}"
21 | ANTIGEN_SYSTEM_UPDATE_DAYS="{{ zsh_update_interval }}"
22 |
23 | {% if zsh_mc_solarized_skin %}export MC_SKIN="$HOME/.mc/lib/mc-solarized/solarized.ini"{% endif %}
24 |
25 | source "{{ zsh_antigen_path_compat }}/antigen/antigen.zsh"
26 |
27 | antigen use oh-my-zsh
28 |
29 | {% set bundles_enabled = [] %}
30 |
31 | {% for bundle in zsh_antigen_bundles -%}
32 | {%- if bundle is mapping -%}
33 | {% set valid = true -%}
34 | {% set command_not_exists = [] -%}
35 |
36 | {%- if bundle.when is defined and not bundle.when -%}
37 | {% set valid = false -%}
38 | {% endif -%}
39 |
40 | {% if bundle.command is defined -%}
41 | {% for cmd in zsh_register_commands_exists.results -%}
42 | {% if cmd.cmd is defined and cmd.rc != 0 and cmd.item.command == bundle.command -%}
43 | {% if command_not_exists.append(1) %}{% endif -%}
44 | {% endif -%}
45 | {% endfor -%}
46 | {% endif -%}
47 |
48 | {% if valid and not command_not_exists %}
49 | {%- if 'zsh-syntax-highlighting' in bundle.name or 'fast-syntax-highlighting' in bundle.name -%}
50 | # will fixed in zsh-autosuggestion v0.4 - https://github.com/zsh-users/zsh-autosuggestions/pull/218
51 | if (( ZSHRC_LOAD_ONCE++ == 0 )); then
52 | antigen bundle {{ bundle.name }}
53 | fi
54 | {% else -%}
55 | {% if bundles_enabled.append(bundle.name) %}{% endif -%}
56 | antigen bundle {{ bundle.name }}
57 | {% endif -%}
58 | {% endif -%}
59 | {%- else -%}
60 | {% if bundles_enabled.append(bundle) %}{% endif -%}
61 | antigen bundle {{ bundle }}
62 | {% endif %}
63 | {% endfor %}
64 |
65 | POWERLEVEL9K_INSTALLATION_PATH=$ANTIGEN_BUNDLES/bhilburn/powerlevel9k/powerlevel9k.zsh-theme
66 |
67 | antigen theme {{ zsh_antigen_theme }}
68 |
69 | antigen apply
70 |
71 | ###
72 |
73 | {% if not zsh_share_history %}
74 | unsetopt share_history
75 | {% endif %}
76 |
77 |
78 | autoload -Uz copy-earlier-word
79 | zle -N copy-earlier-word
80 |
81 | # hotkeys
82 | {% for hotkey in zsh_hotkeys %}
83 | {% if hotkey.hotkey != '' and (hotkey.bundle is not defined or hotkey.bundle in bundles_enabled) %}
84 | bindkey '{{ hotkey.hotkey }}' {{ hotkey.action }}
85 | {% endif %}
86 | {% endfor %}
87 |
88 | # aliases
89 | {% for alias in zsh_aliases %}
90 | {% if alias.alias != '' and (alias.bundle is not defined or alias.bundle in bundles_enabled) %}
91 | alias '{{ alias.alias }}'="{{ alias.action }}"
92 | {% endif %}
93 | {% endfor %}
94 |
95 | # fzf
96 | export FZF_TMUX=0
97 | export FZF_DEFAULT_OPTS="{{ zsh_fzf_default_opts }}"
98 |
99 | # fzf-widgets: fzf-change-reset-dir
100 | {% if zsh_version is version_compare('5.0', '>=') -%}
101 | autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
102 | add-zsh-hook chpwd chpwd_recent_dirs
103 | {% endif %}
104 | declare -p FZF_WIDGETS_OPTS > /dev/null 2>&1 && FZF_WIDGETS_OPTS[insert-history]="{{ zsh_fzf_ctrl_r_opts }}"
105 | declare -p FZF_WIDGET_OPTS > /dev/null 2>&1 && FZF_WIDGET_OPTS[insert-history]="{{ zsh_fzf_ctrl_r_opts }}"
106 |
107 | # zsh-autosuggestions
108 | ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE={{ zsh_autosuggestions_max_length }}
109 | ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=240" # gray highlight
110 |
111 | # powerlevel9k
112 | POWERLEVEL9K_SHORTEN_DIR_LENGTH={{ zsh_powerlevel9k_shorten_dir_length }}
113 | POWERLEVEL9K_STATUS_VERBOSE={{ zsh_powerlevel9k_status_verbose }}
114 |
115 | POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=({{ zsh_powerlevel9k_left_prompt | join(" ") }})
116 | POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=({{ zsh_powerlevel9k_right_prompt | join(" ") }})
117 | {% if zsh_powerlevel9k_hide_host_on_local and zsh_user != 'root' %}DEFAULT_USER=$USER{% endif %}
118 |
119 | POWERLEVEL9K_ALWAYS_SHOW_CONTEXT={{ zsh_powerlevel9k_always_show_context_bool }}
120 | POWERLEVEL9K_ALWAYS_SHOW_USER={{ zsh_powerlevel9k_always_show_user_bool }}
121 |
122 | {% if zsh_powerlevel_custom_elements is defined and zsh_powerlevel_custom_elements %}
123 | {% for element in zsh_powerlevel_custom_elements %}
124 | {% set prefix = "POWERLEVEL9K_CUSTOM_" + element.name | upper %}
125 | {{ prefix }}="{{ element.command }}"
126 | {{ prefix }}_BACKGROUND="{{ element.background }}"
127 | {{ prefix }}_FOREGROUND="{{ element.foreground }}"
128 | {% endfor %}
129 | {% endif %}
130 |
131 | # https://github.com/bhilburn/powerlevel9k#command_execution_time
132 | POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD="{{ zsh_command_time_min_seconds }}"
133 |
134 | POWERLEVEL9K_PROMPT_ON_NEWLINE={{ zsh_powerlevel9k_prompt_on_newline_bool }}
135 | POWERLEVEL9K_RPROMPT_ON_NEWLINE=false
136 | POWERLEVEL9K_PROMPT_ADD_NEWLINE=true
137 |
138 | POWERLEVEL9K_CONTEXT_DEFAULT_FOREGROUND="{{ zsh_powerlevel9k_context_default_foreground }}"
139 | POWERLEVEL9K_CONTEXT_DEFAULT_BACKGROUND="{{ zsh_powerlevel9k_context_default_background }}"
140 | POWERLEVEL9K_CONTEXT_REMOTE_FOREGROUND="{{ zsh_powerlevel9k_context_default_foreground }}"
141 | POWERLEVEL9K_CONTEXT_REMOTE_BACKGROUND="{{ zsh_powerlevel9k_context_default_background }}"
142 | POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND="{{ zsh_powerlevel9k_context_root_foreground }}"
143 | POWERLEVEL9K_CONTEXT_ROOT_BACKGROUND="{{ zsh_powerlevel9k_context_root_background }}"
144 |
145 | POWERLEVEL9K_DIR_DEFAULT_FOREGROUND="{{ zsh_powerlevel9k_dir_foreground }}"
146 | POWERLEVEL9K_DIR_DEFAULT_BACKGROUND="{{ zsh_powerlevel9k_dir_background }}"
147 | POWERLEVEL9K_DIR_HOME_FOREGROUND="{{ zsh_powerlevel9k_dir_foreground }}"
148 | POWERLEVEL9K_DIR_HOME_BACKGROUND="{{ zsh_powerlevel9k_dir_background }}"
149 | POWERLEVEL9K_DIR_HOME_SUBFOLDER_FOREGROUND="{{ zsh_powerlevel9k_dir_foreground }}"
150 | POWERLEVEL9K_DIR_HOME_SUBFOLDER_BACKGROUND="{{ zsh_powerlevel9k_dir_background }}"
151 | POWERLEVEL9K_DIR_ETC_FOREGROUND="{{ zsh_powerlevel9k_dir_etc_foreground }}"
152 | POWERLEVEL9K_DIR_ETC_BACKGROUND="{{ zsh_powerlevel9k_dir_etc_background }}"
153 | POWERLEVEL9K_DIR_PATH_HIGHLIGHT_FOREGROUND="{{ zsh_powerlevel9k_dir_path_highlight_foreground }}"
154 | POWERLEVEL9K_DIR_PATH_HIGHLIGHT_BACKGROUND="{{ zsh_powerlevel9k_dir_path_highlight_background }}"
155 |
156 | POWERLEVEL9K_VCS_CLEAN_BACKGROUND="{{ zsh_powerlevel9k_vcs_clean_background }}"
157 | POWERLEVEL9K_VCS_MODIFIED_BACKGROUND="{{ zsh_powerlevel9k_vcs_modified_background }}"
158 | POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND="{{ zsh_powerlevel9k_vcs_untracked_background }}"
159 | POWERLEVEL9K_VCS_CLEAN_FOREGROUND="{{ zsh_powerlevel9k_vcs_foreground }}"
160 | POWERLEVEL9K_VCS_MODIFIED_FOREGROUND="{{ zsh_powerlevel9k_vcs_foreground }}"
161 | POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND="{{ zsh_powerlevel9k_vcs_foreground }}"
162 |
163 | POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND="{{ zsh_powerlevel9k_command_execution_time_foreground }}"
164 | POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND="{{ zsh_powerlevel9k_command_execution_time_background }}"
165 |
166 | # Aliases
167 | alias suser='su -'
168 |
169 | {% if zsh_load_etc_profile %}source /etc/profile{% endif %}
170 |
171 | # user configs
172 | [[ -r /etc/zsh/zshrc.local ]] && source /etc/zsh/zshrc.local
173 | [[ -r "$HOME/.zshrc.local" ]] && source "$HOME/.zshrc.local"
174 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/tests/vagrant.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: all
3 | roles:
4 | - ../..
5 |
--------------------------------------------------------------------------------
/ansible/roles/viasite-ansible.zsh/vars/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | zsh_user_group: "{% if ansible_os_family == 'Darwin' %}staff{% else %}{{ zsh_user }}{% endif %}"
3 | zsh_antigen_path: "{% if zsh_shared %}/usr/share/zsh-config{% else %}~{{ zsh_user }}/.antigen{% endif %}"
4 | zsh_config: "{% if zsh_shared %}/usr/share/zsh-config/.zshrc{% else %}~{{ zsh_user }}/.zshrc{% endif %}"
5 | zsh_antigen_path_compat: "{{ zsh_antigen_path | replace('~' + zsh_user, '$HOME') }}"
6 |
7 | zsh_fzf_os: linux
8 | zsh_fzf_arch: "{% if '64' in ansible_architecture %}amd64{% else %}386{% endif %}"
9 | zsh_fzf_url: "https://github.com/junegunn/fzf-bin/releases/download/{{ zsh_fzf_version }}/fzf-{{ zsh_fzf_version }}-{{ zsh_fzf_os }}_{{ zsh_fzf_arch }}.tgz"
10 | zsh_antigen_fzf_path: "{{ zsh_antigen_path }}/repos/https-COLON--SLASH--SLASH-github.com-SLASH-junegunn-SLASH-fzf.git"
11 | zsh_fzf_default_opts: "--height {{ zsh_fzf_height }}{% if zsh_fzf_reverse %} --reverse{% endif %}{% if zsh_fzf_border %} --border{% endif %}"
12 |
13 | zsh_powerlevel9k_prompt_on_newline_bool: "{% if zsh_powerlevel9k_prompt_on_newline %}true{% else %}false{% endif %}"
14 | zsh_powerlevel9k_always_show_context_bool: "{% if zsh_powerlevel9k_always_show_context %}true{% else %}false{% endif %}"
15 | zsh_powerlevel9k_always_show_user_bool: "{% if zsh_powerlevel9k_always_show_user %}true{% else %}false{% endif %}"
16 |
--------------------------------------------------------------------------------
/docs/SETUP.md:
--------------------------------------------------------------------------------
1 | # Nomad Cluster Setup
2 |
3 | ## Prerequisite
4 |
5 | Before continuing with the setup for Nomad and Consul:
6 |
7 | - Provision DO infra with Terraform.
8 | - Run Ansible Playbook to boostrap the node.
9 |
10 | ### Setup Tailscale
11 |
12 | Tailscale acts as a mesh layer between the server and worker nodes. Since the user's laptop/mobile also has a Tailscale agent running it makes it easy to deploy and browse Nomad/Consul Admin UIs as well.
13 |
14 | ```
15 | sudo tailscale up
16 | ```
17 |
18 | ## Install Nomad
19 |
20 | Follow the instructions from the [docs](https://www.nomadproject.io/docs/install).
21 |
22 | ```sh
23 | curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
24 | sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
25 | sudo apt-get update && sudo apt-get install nomad
26 | nomad -autocomplete-install
27 | complete -C /usr/bin/nomad nomad
28 | sudo mkdir --parents /opt/nomad
29 | ```
30 |
31 | ### Setup Nomad
32 |
33 | Follow the instructions from the [docs](https://learn.hashicorp.com/tutorials/nomad/production-deployment-guide-vm-with-consul).
34 |
35 | #### Systemd unit
36 |
37 | ```
38 | # /etc/systemd/system/nomad.service
39 | [Unit]
40 | Description=Nomad
41 | Documentation=https://www.nomadproject.io/docs
42 | Wants=network-online.target
43 | After=network-online.target
44 |
45 | [Service]
46 | ExecReload=/bin/kill -HUP $MAINPID
47 | ExecStart=/usr/bin/nomad agent -config /etc/nomad.d
48 | KillMode=process
49 | KillSignal=SIGINT
50 | LimitNOFILE=infinity
51 | LimitNPROC=infinity
52 | Restart=on-failure
53 | RestartSec=2
54 | StartLimitBurst=3
55 | StartLimitIntervalSec=10
56 | TasksMax=infinity
57 |
58 | [Install]
59 | WantedBy=multi-user.target
60 | ```
61 |
62 | #### Configurations
63 |
64 | All the config files are stored in `/etc/nomad.d`.
65 |
66 | ```hcl
67 | data_dir = "/opt/nomad/data"
68 | bind_addr = "{{ GetInterfaceIP \"tailscale0\" }}"
69 | datacenter = "hydra"
70 |
71 | server {
72 | enabled = true
73 | bootstrap_expect = 1
74 | }
75 |
76 | client {
77 | enabled = true
78 | host_network "tailscale" {
79 | cidr = "100.119.138.27/32"
80 | reserved_ports = "22"
81 | }
82 | }
83 |
84 | plugin "docker" {
85 | config {
86 | volumes {
87 | enabled = true
88 | }
89 | extra_labels = ["job_name", "job_id", "task_group_name", "task_name", "namespace", "node_name", "node_id"]
90 | }
91 | }
92 |
93 | plugin "raw_exec" {
94 | config {
95 | enabled = true
96 | }
97 | }
98 |
99 | telemetry {
100 | collection_interval = "15s"
101 | disable_hostname = true
102 | prometheus_metrics = true
103 | publish_allocation_metrics = true
104 | publish_node_metrics = true
105 | }
106 |
107 | consul {
108 | address = "100.119.138.27:8500"
109 | }
110 | ```
111 |
112 | ### Verification
113 |
114 | Since we changed the `bind_addr` from `0.0.0.0`(default) to Tailscale IP we need to
115 | configure `NOMAD_ADDRESS` env variable for CLI to configure the remote endpoint:
116 |
117 | [Docs](https://www.nomadproject.io/docs/commands#remote-usage)
118 |
119 | ```sh
120 | export NOMAD_ADDR=http://100.119.138.27:4646
121 | ```
122 |
123 | Before proceeding ahead, make sure `nomad` is running:
124 |
125 | ```sh
126 | $ nomad server members
127 | Name Address Port Status Leader Protocol Build Datacenter Region
128 | floyd.global 10.47.0.6 4648 alive true 2 1.0.3 hydra global
129 | ```
130 |
131 | ## Install Consul
132 |
133 | ```sh
134 | sudo apt-get update && sudo apt-get install consul
135 | consul -autocomplete-install
136 | complete -C /usr/bin/consul consul
137 | sudo mkdir --parents /opt/consul
138 | ```
139 |
140 | ## Setup Consul
141 |
142 | ### Generate Keys
143 |
144 | ```
145 | consul keygen
146 | ```
147 |
148 | The output of the above command is used in the config file.
149 |
150 | ### Configuration
151 |
152 | All the config is stored in `/etc/consul.d`
153 |
154 | ```hcl
155 | datacenter = "hydra"
156 | data_dir = "/opt/consul/data"
157 | encrypt = ""
158 | server = true
159 | bootstrap_expect = 1
160 | client_addr = "100.119.138.27"
161 | bind_addr = "127.0.0.1"
162 | ui = true
163 | connect {
164 | enabled = true
165 | }
166 | ```
167 |
168 | ### Systemd Unit
169 |
170 | ```
171 | [Unit]
172 | Description="HashiCorp Consul - A service mesh solution"
173 | Documentation=https://www.consul.io/
174 | Requires=network-online.target
175 | After=network-online.target
176 | ConditionFileNotEmpty=/etc/consul.d/consul.hcl
177 |
178 | [Service]
179 | User=consul
180 | Group=consul
181 | ExecStart=/usr/bin/consul agent -config-dir=/etc/consul.d/
182 | ExecReload=/bin/kill --signal HUP $MAINPID
183 | KillMode=process
184 | KillSignal=SIGTERM
185 | Restart=on-failure
186 | LimitNOFILE=65536
187 |
188 | [Install]
189 | WantedBy=multi-user.target
190 | ```
191 |
192 | ## Vault
193 |
194 | **WIP**
195 |
196 | Currently using `TF_VARS` to load env variables from the host and run `tf apply`. Terraform then templates out the Nomad `jobspec` and submits the job to the server. This is okay in this context because:
197 |
198 | - Nomad API server is listening only to Tailscale IP. Which means only trusted, authenticated agents have access to the API. This is very important because Nomad shows the plain text version of the `jobspec` in UI and CLI. So all the secret keys can be exposed if a malicious actor has access to the API server (even if read only).
199 |
200 | - The env keys are mostly just one time API tokens or DB Passwords. They don't need to be "watched" and reloaded often, running an entire Vault server just for passing these keys seems a bit _extra complexity_.
201 |
202 | **However**, to just _experiment_ with things and make the setup a bit more secure, we can consider running a single node Vault server:
203 |
204 | - [ ] Setup Vault to store secrets
205 | - [ ] Vault init/unseal steps.
206 | - [ ] Add Policies and Role in Vault for a namespace
207 | - [ ] Configure Nomad to use Vault
208 | - [ ] Add an API token in Vault
209 | - [ ] Pass CF token to Caddyfile and retrieve from Vault with Consul Template
210 |
--------------------------------------------------------------------------------
/docs/calvin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mr-karan/homelab/06653f8f276e53b3ef987d80ce65b7d7e190cdce/docs/calvin.jpg
--------------------------------------------------------------------------------
/talks/foss-united-apr-2021.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/talks/foss-united-apr-2021.md:
--------------------------------------------------------------------------------
1 | ---
2 | theme: dracula
3 | paginate: true
4 | marp: true
5 | size: 4K
6 | footer: Hydra Repo: [git.mrkaran.dev/karan/hydra](https://git.mrkaran.dev/karan/hydra)
7 | ---
8 |
9 |
10 |
11 | # Self Hosting 101
12 |
13 | FOSS United - April 2021
14 |
15 | *@mrkaran*
16 |
17 | ---
18 |
19 | # `whoami`
20 |
21 | 👨💻 Writes YAML at Zerodha
22 |
23 | 📈 Interested in Monitoring and Observability systems
24 |
25 | 📓 Blogs about things I find interesting
26 |
27 | 🧩 **Self hosted enthusiast**
28 |
29 | 
30 |
31 | ---
32 |
33 | # Why (I) Self Host
34 |
35 | - Break from the Big Tech Co
36 |
37 | ---
38 |
39 | # Why (I) Self Host
40 |
41 | - Break from the Big Tech Co
42 | - Own your data
43 |
44 | ---
45 |
46 | # Why (I) Self Host
47 |
48 | - Break from the Big Tech Co
49 | - Own your data
50 | - No lock ins for data which is critical
51 |
52 | ---
53 |
54 | # Why (I) Self Host
55 |
56 | - Break from the Big Tech Co
57 | - Own your data
58 | - No lock ins for data which is critical
59 | - Chance to contribute to OSS
60 |
61 | ---
62 |
63 | # Why (I) Self Host
64 |
65 | - Break from the Big Tech Co
66 | - Own your data
67 | - No lock ins for data which is critical
68 | - Chance to contribute to OSS
69 | - Experiment and learn
70 |
71 | ---
72 |
73 | # My Setup
74 |
75 | ## Servers
76 |
77 | - DigitalOcean Droplet (2vCPU, 4GB RAM, blr1 Region)
78 | - 1 * RPi 4 Node (4GB RAM)
79 | - 1 * RPi 4 Node (2GB RAM)
80 |
81 | ---
82 |
83 | # Infra and Deployments
84 |
85 | - Ansible
86 | - Terraform
87 | - Nomad + Consul
88 |
89 | ---
90 |
91 | ## Ansible
92 |
93 | - Boostrap the server
94 | - Harden SSH. User, Shell setups.
95 | - Install `node-exporter`, `docker`, `tailscale`.
96 |
97 | ---
98 |
99 | ## Terraform
100 |
101 | - DigitalOcean infra
102 | - Droplet
103 | - Firewalls
104 | - SSH Keys, Volumes, Floating IPs etc.
105 |
106 | - Cloudflare DNS
107 | - `mrkaran.dev` hosted zone
108 | - DNS Records in ^ the zone.
109 |
110 | ---
111 |
112 | ## Nomad + Consul
113 |
114 | - Single node cluster.
115 | - Runs every workload (mostly) as a docker container.
116 |
117 | ---
118 |
119 | # Services I run
120 |
121 | - Pi-hole
122 | - Gitea
123 | - Joplin Sync Server
124 | - Shynet
125 | - Firefly III
126 | - Nextcloud
127 | - `doggo` (Shameless self plug)
128 |
129 | ---
130 |
131 | # Monitoring
132 |
133 | - Grafana
134 | - Prometheus
135 | - Telegraf to collect home ISP stats
136 | - Ping Input plugin
137 | - DNS Input Plugin
138 |
139 | ---
140 |
141 | 
142 |
143 | ---
144 |
145 | 
146 |
147 | ---
148 |
149 | # Networking
150 |
151 | - Tailscale for Mesh Network
152 | - Based on Wireguard VPN.
153 | - Authenticated sessions only.
154 | - Expose services on RPi easily without any static IP.
155 |
156 | ---
157 |
158 | # Networking
159 |
160 | - Caddy as a proxy for all services.
161 | - Running 2 instances of Caddy.
162 | - Private: Listens on Tailscale Interface.
163 | - Public: Listens on DO's public IPv4 Interface.
164 |
165 | - Automatic SSL with ACME DNS challenge
166 | - Built my own image: https://github.com/mr-karan/caddy-plugins-docker
167 |
168 | ---
169 |
170 | # Storage
171 |
172 | - DONT use RPi for storage.
173 | - Atleast not with SD cards.
174 | - Newer RPis can boot off SSDs.
175 |
176 | - Enable snapshots for volumes provided by cloud provider.
177 |
178 | - Use separate DB instances for different applications.
179 |
180 | ---
181 |
182 | # Backups
183 |
184 | - Restic
185 | - Periodic Job in Nomad.
186 | - Single vault with everything inside `/data`.
187 | - All applications mount inside `/data` folder.
188 | - Upload to Backblaze B2.
189 |
190 | ---
191 |
192 | # Security
193 |
194 | - If it should not be public facing, don't expose to WWW.
195 | - Prefer to use a VPN or mesh network instead of IP whitelists.
196 | - Tighter Firewall rules otherwise.
197 |
198 | - Pi-Hole, Gitea, etc Admin interfaces must always be protected with strong passwords.
199 | - Wonder how many `admin/admin` Grafana instances are out in open.
200 | - Or worse, no auth. Looking at you Elasticsearch.
201 |
202 | - Periodic **updates** to App and OS.
203 |
204 | ---
205 |
206 | # Takeaways
207 |
208 | - Don't overthink. Pick something really simple (like Pi-hole) and host it.
209 | - You'll feel pretty happy about it.
210 |
211 | - Don't blindly copy/paste this stack.
212 | - Took me 2 years of constant iteration and experimentation.
213 | - KISS.
214 |
215 | ---
216 |
217 | # Resources
218 |
219 | [r/selfhosted](https://www.reddit.com/r/selfhosted)
220 | - Incredible, beginner friendly wiki: https://wiki.r-selfhosted.com/
221 | [github.com/awesome-selfhosted](https://github.com/awesome-selfhosted/awesome-selfhosted)
222 |
223 | ---
224 |
225 |
226 |
227 |
228 | # Thank You
229 |
230 | ## Questions?
231 |
--------------------------------------------------------------------------------
/talks/img/cycle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mr-karan/homelab/06653f8f276e53b3ef987d80ce65b7d7e190cdce/talks/img/cycle.jpg
--------------------------------------------------------------------------------
/talks/img/isp-monitoring-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mr-karan/homelab/06653f8f276e53b3ef987d80ce65b7d7e190cdce/talks/img/isp-monitoring-2.png
--------------------------------------------------------------------------------
/talks/img/isp-monitoring.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mr-karan/homelab/06653f8f276e53b3ef987d80ce65b7d7e190cdce/talks/img/isp-monitoring.png
--------------------------------------------------------------------------------
/terraform/.terraform.lock.hcl:
--------------------------------------------------------------------------------
1 | # This file is maintained automatically by "terraform init".
2 | # Manual edits may be lost in future updates.
3 |
4 | provider "registry.terraform.io/cloudflare/cloudflare" {
5 | version = "2.20.0"
6 | hashes = [
7 | "h1:hq912gbF5V9qU6O6TpIjDecKCOpZ3s/o0HIZAIESlw8=",
8 | "zh:1cc439dcf2bb64fbc4b701e0345d47e32c488ebf3c5149c4b2a5da5b1f9b8dc5",
9 | "zh:2b244c594bf674d7f3d939f75daae6bc68732f62603c179d63c8c16b4cd5c248",
10 | "zh:3210c5e6bae1595f231f5e0a479c305b97192d5393b7e6650c6d3647f382041f",
11 | "zh:332f9ac6aa5c18e2df20f177f59cd68ec4c4a46b30e46d7a0af37fffeaed90ca",
12 | "zh:3e304aca15904cde3cf60e23de3422d4dbd84f1b527f587b7d6009f722d8645e",
13 | "zh:5a4ff4512ed12fde14d27ff8ac2e76d3bbea2e39ccc12f0720292c0ebe4a3bf8",
14 | "zh:71dd3268b5e9cb50831254451a6c2b4a3da4383c852b9e37b19ba94b63555532",
15 | "zh:841dfe03377d38667541359c7b5857ff48df4d1cee12f63daadc5837e4ca1974",
16 | "zh:8fa108c7d8b9e1edcdc2aa8be18a054d5e00c67137e29f27c16dc5e2fdcf76b7",
17 | "zh:a38823be68ed1d0aed2e0051d459d150372edff396d3d108725bc889b91cd41f",
18 | "zh:a6c4f12bb0ab72f381eff0172790b00ab35fd6f7f14c60f56a1d67a0bb3225ea",
19 | "zh:bcc00547d0c6ccefe277aa16f5764d4621b0fe76579ab683bb88df192f107c12",
20 | "zh:ca3922155eb365402b8b661c32fb7f9324fecfab7d627810fb9a425fa44ec534",
21 | ]
22 | }
23 |
24 | provider "registry.terraform.io/digitalocean/digitalocean" {
25 | version = "2.5.1"
26 | constraints = "2.5.1"
27 | hashes = [
28 | "h1:k9itTwJzUpMBTYsXYPoEW/fyoDOcteQc4+OMRmFErbc=",
29 | "zh:057b8fa0f95213e7d856208d456175335fb673cfef14abf41193f0a2d76e1210",
30 | "zh:0daee13dd46de95ce2550459942c1433290798bfb5faac12781f81799dd6b05c",
31 | "zh:13778c00db5c43b2ed5781e2de32d73f34b391c865a52ad3380714bf86251785",
32 | "zh:2b2bbb1b057c8bf15804a9fd47c30f30b39bcd7ed478bfcad11e221c654f5d02",
33 | "zh:43284d2b1a356f541723a46219812590d24742558ef4111eda545212fd60f011",
34 | "zh:6a6e13b55f9aa889e3162d75cb3e585116e8a0d12084629af38f68cdac6aa777",
35 | "zh:6fa3dbbad99a075768e9449fc6082769da1b76ae31a8e296ae50899835e859a1",
36 | "zh:79336598d190f511cf3d3323b49081474669d0daa9c1c0d3b21475110ad97bd9",
37 | "zh:84c4c8d29820229bd94f7d3c5310f1f7208b97e7d4efca2c8e24ae0c0e032267",
38 | "zh:86926853140d9072986d2cb8ff4693784abd5f5d241b8cec402dfad77d8060ed",
39 | "zh:95a896f51656b51519b10edf38f11eb766de60297b8551dc0d14a4041dd16d6f",
40 | "zh:d163da24466cd60eed4749fef56c6593cc6e33be2e210e1b57edfd1c968aa742",
41 | "zh:e830649afac9e505603002f8a76b2441a0a41c96c6516609e2c07ce0c45f9dc3",
42 | ]
43 | }
44 |
45 | provider "registry.terraform.io/hashicorp/http" {
46 | version = "2.1.0"
47 | hashes = [
48 | "h1:HmUcHqc59VeHReHD2SEhnLVQPUKHKTipJ8Jxq67GiDU=",
49 | "zh:03d82dc0887d755b8406697b1d27506bc9f86f93b3e9b4d26e0679d96b802826",
50 | "zh:0704d02926393ddc0cfad0b87c3d51eafeeae5f9e27cc71e193c141079244a22",
51 | "zh:095ea350ea94973e043dad2394f10bca4a4bf41be775ba59d19961d39141d150",
52 | "zh:0b71ac44e87d6964ace82979fc3cbb09eb876ed8f954449481bcaa969ba29cb7",
53 | "zh:0e255a170db598bd1142c396cefc59712ad6d4e1b0e08a840356a371e7b73bc4",
54 | "zh:67c8091cfad226218c472c04881edf236db8f2dc149dc5ada878a1cd3c1de171",
55 | "zh:75df05e25d14b5101d4bc6624ac4a01bb17af0263c9e8a740e739f8938b86ee3",
56 | "zh:b4e36b2c4f33fdc44bf55fa1c9bb6864b5b77822f444bd56f0be7e9476674d0e",
57 | "zh:b9b36b01d2ec4771838743517bc5f24ea27976634987c6d5529ac4223e44365d",
58 | "zh:ca264a916e42e221fddb98d640148b12e42116046454b39ede99a77fc52f59f4",
59 | "zh:fe373b2fb2cc94777a91ecd7ac5372e699748c455f44f6ea27e494de9e5e6f92",
60 | ]
61 | }
62 |
63 | provider "registry.terraform.io/hashicorp/nomad" {
64 | version = "1.4.14"
65 | constraints = "1.4.14"
66 | hashes = [
67 | "h1:GxsjoJKg/PWeXYzpzoONBQiaGnY+bPEDDD+BsEDgc8Q=",
68 | "zh:036cc8e0c1c6c2f91573149910eca29a7107b3415536eabeb2581861525da64a",
69 | "zh:1414e2deb87af66a47e44ab5472b4606294cf511722beae2c0a3680041d66635",
70 | "zh:623184a22b347fa5b696d3fbee35f5bff9ed30fbc8b067715c52b6300d655789",
71 | "zh:7a026a57148a7c2e8a08a83c3641898911a7d9998c38eb2c6ca634107ccf49f9",
72 | "zh:87d34e879284453b2ac825f8bb9c88c85027d404b1b9fa445ec97b519dfa59cb",
73 | "zh:90591119307c2f3dd15a6a78964731689444fb1ce3d393eddf83e05a2f187b80",
74 | "zh:b2cbf5e4d4f2d500804e7f1968b3fd2cebd4b164ccf76d7cb2c99ed1eb23957e",
75 | "zh:d5f19ab3d0d172be8af098bb62b47667c632af736c60d1acab0fc1c31dbbcb99",
76 | "zh:ee5f7f75a642eed607d4824b5888e4aacfc4dd435d54d9523d8f8165695d52a1",
77 | "zh:f6300309339221a5f0863bec32d96b38a8e545c5a87b43c5bb8c65d2ff0492ed",
78 | ]
79 | }
80 |
81 | provider "registry.terraform.io/hashicorp/template" {
82 | version = "2.2.0"
83 | hashes = [
84 | "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=",
85 | "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386",
86 | "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53",
87 | "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603",
88 | "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16",
89 | "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776",
90 | "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451",
91 | "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae",
92 | "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde",
93 | "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d",
94 | "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2",
95 | ]
96 | }
97 |
98 | provider "registry.terraform.io/kreuzwerker/docker" {
99 | version = "2.11.0"
100 | hashes = [
101 | "h1:2BuPcSQY9DSRhPufzrbiGyMW2NX1qqXkH1KfzrMUQmU=",
102 | "zh:1b9d93385cc0329467725ce90affc76a361bc23384a7358431e6ee281ae323de",
103 | "zh:21a327746cdad2abfc22df3d72eb9b36134bb7daeb72b2a52112adfd3a39555a",
104 | "zh:31ed477f429686015271188b03e89bfc400b74eea9e83956ea4cc16018b561f3",
105 | "zh:4302d65b5cbedbe42cf35094748058aea44f75dd7ec2b257330b5f60a2521def",
106 | "zh:43f53e3e29070dfec0621915d0a5266c386f7416f6a719531b7c55924cefd280",
107 | "zh:4bf7704bf46868edd834991f350aa6204c72397be1e1a784278391bb911e29f5",
108 | "zh:503434ddf9c801aa9a9e47e76b6b5758dd4583a49f7ac373066430b37b3efcaf",
109 | "zh:67410f9ed6503692121519b81e13cf5274ceadb5566bf2ec2dc0a6e43c700621",
110 | "zh:c0fd724ed8da52375976c3595a2a6748bf28c07ec881ad7154e657ab5c38f25b",
111 | "zh:cbe762d96c4ae61c42d8c02c047954b52a6567b214a0263345135baf249accd7",
112 | "zh:d3a23b086199d4a2a63707f28c0da8b392d8d11281c6881d85a959e76626fb7e",
113 | ]
114 | }
115 |
--------------------------------------------------------------------------------
/terraform/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: init plan apply lint
2 |
3 | plan:
4 | - terraform plan
5 |
6 | init:
7 | - terraform init
8 |
9 | apply:
10 | # that's how we roll here ;)
11 | - terraform apply -auto-approve
12 |
13 | lint:
14 | - terraform validate && terraform fmt -recursive
15 |
--------------------------------------------------------------------------------
/terraform/env.sample:
--------------------------------------------------------------------------------
1 | DIGITALOCEAN_TOKEN=
2 | CLOUDFLARE_API_TOKEN=
3 | TF_VAR_cloudflare_caddy_api_token=
4 | TF_VAR_shynet_postgresql_password=
5 | TF_VAR_shynet_django_secret_key=
6 | TF_VAR_gitea_secret_key=
7 | TF_VAR_gitea_internal_token=
8 | TF_VAR_gitea_lfs_jwt_secret=
9 | TF_VAR_gitea_oauth2_jwt_secret=
10 | TF_VAR_restic_b2_account_id=
11 | TF_VAR_restic_b2_account_key=
12 | TF_VAR_restic_repository=
13 | TF_VAR_restic_password=
--------------------------------------------------------------------------------
/terraform/main.tf:
--------------------------------------------------------------------------------
1 | module "servers" {
2 | source = "./modules/digitalocean"
3 | providers = {
4 | digitalocean = digitalocean
5 | }
6 | }
7 |
8 | module "cloudflare" {
9 | source = "./modules/cloudflare"
10 | ips = local.ips
11 | providers = {
12 | cloudflare = cloudflare
13 | }
14 | }
15 |
16 | module "caddy" {
17 | source = "./modules/caddy"
18 | cloudflare_api_token = var.cloudflare_caddy_api_token
19 | providers = {
20 | nomad = nomad
21 | }
22 | }
23 |
24 | module "pihole" {
25 | source = "./modules/pihole"
26 | providers = {
27 | nomad = nomad
28 | }
29 | }
30 |
31 |
32 | module "doggo" {
33 | source = "./modules/doggo"
34 | providers = {
35 | nomad = nomad
36 | }
37 | }
38 |
39 | module "shynet" {
40 | source = "./modules/shynet"
41 | shynet_postgresql_password = var.shynet_postgresql_password
42 | shynet_django_secret_key = var.shynet_django_secret_key
43 | providers = {
44 | nomad = nomad
45 | }
46 | }
47 |
48 | module "restic" {
49 | source = "./modules/restic"
50 | restic_b2_account_id = var.restic_b2_account_id
51 | restic_b2_account_key = var.restic_b2_account_key
52 | restic_repository = var.restic_repository
53 | restic_password = var.restic_password
54 | providers = {
55 | nomad = nomad
56 | }
57 | }
58 |
59 |
60 | module "gitea" {
61 | source = "./modules/gitea"
62 | gitea_secret_key = var.gitea_secret_key
63 | gitea_internal_token = var.gitea_internal_token
64 | gitea_lfs_jwt_secret = var.gitea_lfs_jwt_secret
65 | gitea_oauth2_jwt_secret = var.gitea_oauth2_jwt_secret
66 | providers = {
67 | nomad = nomad
68 | }
69 | }
70 |
71 | module "monitoring" {
72 | source = "./modules/monitoring"
73 | providers = {
74 | nomad = nomad
75 | }
76 | }
77 |
78 | module "syncthing" {
79 | source = "./modules/syncthing"
80 | providers = {
81 | nomad = nomad
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/terraform/modules/caddy/conf/Caddyfile-internal:
--------------------------------------------------------------------------------
1 | nomad.mrkaran.dev {
2 | reverse_proxy 100.119.138.27:4646
3 | tls {
4 | dns cloudflare "${cloudflare_api_token}"
5 | }
6 | }
7 |
8 | consul.mrkaran.dev {
9 | reverse_proxy 100.119.138.27:8500
10 | tls {
11 | dns cloudflare "${cloudflare_api_token}"
12 | }
13 | }
14 |
15 | pihole.mrkaran.dev {
16 | {{ range service "pihole-admin" }}
17 | reverse_proxy {{ .Address }}:{{ .Port }}
18 | {{ end }}
19 | tls {
20 | dns cloudflare "${cloudflare_api_token}"
21 | }
22 | }
23 |
24 | grafana.mrkaran.dev {
25 | {{ range service "grafana-web" }}
26 | reverse_proxy {{ .Address }}:{{ .Port }}
27 | {{ end }}
28 | tls {
29 | dns cloudflare "${cloudflare_api_token}"
30 | }
31 | }
32 |
33 | prometheus.mrkaran.dev {
34 | {{ range service "prometheus-web" }}
35 | reverse_proxy {{ .Address }}:{{ .Port }}
36 | {{ end }}
37 | tls {
38 | dns cloudflare "${cloudflare_api_token}"
39 | }
40 | }
41 |
42 | syncthing.mrkaran.dev {
43 | {{ range service "syncthing-web" }}
44 | reverse_proxy {{ .Address }}:{{ .Port }}
45 | {{ end }}
46 | tls {
47 | dns cloudflare "${cloudflare_api_token}"
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/terraform/modules/caddy/conf/Caddyfile-public:
--------------------------------------------------------------------------------
1 | shynet.mrkaran.dev {
2 | {{ range service "shynet-web" }}
3 | reverse_proxy {{ .Address }}:{{ .Port }}
4 | {{ end }}
5 | tls {
6 | dns cloudflare "${cloudflare_api_token}"
7 | }
8 | }
9 |
10 | git.mrkaran.dev {
11 | {{ range service "gitea-web" }}
12 | reverse_proxy {{ .Address }}:{{ .Port }}
13 | {{ end }}
14 | tls {
15 | dns cloudflare "${cloudflare_api_token}"
16 | }
17 | }
18 |
19 | doggo.mrkaran.dev {
20 | {{ range service "doggo-web" }}
21 | reverse_proxy {{ .Address }}:{{ .Port }}
22 | {{ end }}
23 | tls {
24 | dns cloudflare "${cloudflare_api_token}"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/terraform/modules/caddy/conf/caddy.nomad:
--------------------------------------------------------------------------------
1 | job "caddy" {
2 | datacenters = ["hydra"]
3 | type = "service"
4 |
5 | group "proxy" {
6 | count = 1
7 |
8 | network {
9 | port "http-internal" {
10 | static = 80
11 | to = 80
12 | host_network = "tailscale"
13 | }
14 |
15 | port "https-internal" {
16 | static = 443
17 | to = 443
18 | host_network = "tailscale"
19 | }
20 |
21 | port "https-public" {
22 | static = 80
23 | to = 80
24 |
25 | # host_network = "public"
26 | }
27 |
28 | port "http-public" {
29 | static = 443
30 | to = 443
31 |
32 | # host_network = "public"
33 | }
34 | }
35 |
36 | restart {
37 | attempts = 2
38 | interval = "2m"
39 | delay = "30s"
40 | mode = "fail"
41 | }
42 |
43 | task "internal" {
44 | driver = "docker"
45 |
46 | config {
47 | image = "mrkaran/caddy:latest"
48 |
49 | # Bind the config file to container.
50 | mount {
51 | type = "bind"
52 | source = "configs"
53 | target = "/etc/caddy" # Bind mount the template from `NOMAD_TASK_DIR`.
54 | }
55 |
56 | # Bind the data directory to preserve certs.
57 | mount {
58 | type = "bind"
59 | target = "/data"
60 | source = "/data/caddy"
61 | readonly = false
62 | }
63 |
64 | ports = ["http-internal", "https-internal"]
65 | }
66 |
67 | resources {
68 | cpu = 100
69 | memory = 100
70 | }
71 |
72 | template {
73 | data = <
11 | ```
12 |
13 | ```shell
14 | tf init
15 | ```
16 |
17 | ## Applying changes
18 |
19 | ```shell
20 | tf plan
21 | tf apply
22 | ```
23 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/firewalls.tf:
--------------------------------------------------------------------------------
1 | data "http" "cloudflare_ip4_addrs" {
2 | url = "https://www.cloudflare.com/ips-v4"
3 | }
4 |
5 | data "http" "cloudflare_ip6_addrs" {
6 | url = "https://www.cloudflare.com/ips-v6"
7 | }
8 |
9 | resource "digitalocean_firewall" "web" {
10 | name = "allow-http-https-cloudflare"
11 |
12 | droplet_ids = [digitalocean_droplet.floyd.id]
13 | inbound_rule {
14 | protocol = "tcp"
15 | port_range = "80"
16 | source_addresses = concat(
17 | split("\n", trimspace(data.http.cloudflare_ip4_addrs.body)),
18 | split("\n", trimspace(data.http.cloudflare_ip6_addrs.body))
19 | )
20 | }
21 |
22 | inbound_rule {
23 | protocol = "tcp"
24 | port_range = "443"
25 | source_addresses = concat(
26 | split("\n", trimspace(data.http.cloudflare_ip4_addrs.body)),
27 | split("\n", trimspace(data.http.cloudflare_ip6_addrs.body))
28 | )
29 | }
30 |
31 | }
32 |
33 | resource "digitalocean_firewall" "icmp" {
34 | name = "allow-icmp-all"
35 |
36 | droplet_ids = [digitalocean_droplet.floyd.id]
37 | inbound_rule {
38 | protocol = "icmp"
39 | source_addresses = ["0.0.0.0/0", "::/0"]
40 | }
41 |
42 | }
43 |
44 | resource "digitalocean_firewall" "vpn" {
45 | name = "allow-all-tailscale-inbound"
46 |
47 | droplet_ids = [digitalocean_droplet.floyd.id]
48 |
49 | inbound_rule {
50 | protocol = "tcp"
51 | port_range = "1-65535"
52 | source_addresses = ["100.64.0.0/10"]
53 | }
54 |
55 | inbound_rule {
56 | protocol = "udp"
57 | port_range = "1-65535"
58 | source_addresses = ["100.64.0.0/10"]
59 | }
60 |
61 | }
62 |
63 | resource "digitalocean_firewall" "ssh" {
64 | name = "ssh-inbound"
65 |
66 | droplet_ids = [digitalocean_droplet.floyd.id]
67 |
68 | inbound_rule {
69 | protocol = "tcp"
70 | port_range = "22"
71 | source_addresses = ["0.0.0.0/0", "::/0"]
72 | }
73 | }
74 |
75 |
76 | resource "digitalocean_firewall" "outbound-all" {
77 | name = "allow-all-outbound"
78 |
79 | droplet_ids = [digitalocean_droplet.floyd.id]
80 |
81 | outbound_rule {
82 | protocol = "tcp"
83 | port_range = "1-65535"
84 | destination_addresses = ["0.0.0.0/0", "::/0"]
85 | }
86 |
87 | outbound_rule {
88 | protocol = "udp"
89 | port_range = "1-65535"
90 | destination_addresses = ["0.0.0.0/0", "::/0"]
91 | }
92 |
93 | outbound_rule {
94 | protocol = "icmp"
95 | destination_addresses = ["0.0.0.0/0", "::/0"]
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/floyd.tf:
--------------------------------------------------------------------------------
1 | # `floyd` is the Nomad Serve which also runs Consul, Vault.
2 | resource "digitalocean_droplet" "floyd" {
3 | image = "ubuntu-20-04-x64"
4 | name = "floyd"
5 | region = "blr1"
6 | monitoring = true
7 | size = "s-2vcpu-4gb"
8 | ipv6 = true
9 | private_networking = true
10 | tags = [
11 | "nomad",
12 | "control-plane"
13 | ]
14 | ssh_keys = [digitalocean_ssh_key.mrkaran.fingerprint]
15 | }
16 |
17 | # Attach the floating ip to droplet
18 | resource "digitalocean_floating_ip" "floyd" {
19 | droplet_id = digitalocean_droplet.floyd.id
20 | region = digitalocean_droplet.floyd.region
21 | }
22 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/output.tf:
--------------------------------------------------------------------------------
1 | output "floating_floyd" {
2 | value = digitalocean_floating_ip.floyd.ip_address
3 | description = "Floating IP of Floyd Node"
4 | }
5 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/project.tf:
--------------------------------------------------------------------------------
1 | # `hydra` tags all the resources assosciated with it under a project.
2 | resource "digitalocean_project" "hydra" {
3 | name = "hydra"
4 | description = "Self hosted Nomad cluster to deploy personal workloads"
5 | purpose = "Web Application"
6 | environment = "Production"
7 | # Tag the droplet IDs and Floating IPs.
8 | resources = [digitalocean_droplet.floyd.urn, digitalocean_floating_ip.floyd.urn]
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/ssh.tf:
--------------------------------------------------------------------------------
1 | # Common SSH key which is attached to all servers.
2 | resource "digitalocean_ssh_key" "mrkaran" {
3 | name = "mrkaran.dev"
4 | public_key = file("~/.ssh/mrkaran_rsa.pub")
5 | }
6 |
--------------------------------------------------------------------------------
/terraform/modules/digitalocean/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | digitalocean = {
4 | source = "digitalocean/digitalocean"
5 | }
6 | }
7 | required_version = ">= 0.13"
8 | }
9 |
--------------------------------------------------------------------------------
/terraform/modules/doggo/conf/doggo.nomad:
--------------------------------------------------------------------------------
1 | job "doggo" {
2 | datacenters = ["hydra"]
3 | type = "service"
4 |
5 | group "app" {
6 | count = 1
7 |
8 | network {
9 | port "http" {
10 | to = 8080
11 | }
12 | }
13 |
14 | restart {
15 | attempts = 2
16 | interval = "2m"
17 | delay = "30s"
18 | mode = "fail"
19 | }
20 |
21 | task "web" {
22 | driver = "docker"
23 |
24 | service {
25 | name = "doggo-web"
26 | tags = ["doggo", "web"]
27 | port = "http"
28 | }
29 |
30 | config {
31 | image = "ghcr.io/mr-karan/doggo-api:v0.4.0"
32 |
33 | ports = ["http"]
34 |
35 | logging {
36 | type = "json-file"
37 | config {
38 | labels = "com.hashicorp.nomad.alloc_id,com.hashicorp.nomad.job_id,com.hashicorp.nomad.job_name,com.hashicorp.nomad.namespace,com.hashicorp.nomad.node_id,com.hashicorp.nomad.node_name,com.hashicorp.nomad.task_group_name,com.hashicorp.nomad.task_name"
39 | }
40 | }
41 | }
42 |
43 | resources {
44 | cpu = 200
45 | memory = 200
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/terraform/modules/doggo/job.tf:
--------------------------------------------------------------------------------
1 | resource "nomad_job" "app" {
2 | jobspec = templatefile("${path.module}/conf/doggo.nomad", {
3 | })
4 | hcl2 {
5 | enabled = true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/terraform/modules/doggo/providers.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | nomad = {
4 | source = "hashicorp/nomad"
5 | version = "1.4.14"
6 | }
7 | }
8 | required_version = ">= 0.14"
9 | }
10 |
--------------------------------------------------------------------------------
/terraform/modules/gitea/conf/app.ini.tpl:
--------------------------------------------------------------------------------
1 | ; This file lists the default values used by Gitea
2 | ; Sample file: https://github.com/go-gitea/gitea/blob/master/custom/conf/app.example.ini
3 | ; Docs: https://docs.gitea.io/en-us/config-cheat-sheet/
4 |
5 | APP_NAME = Code by mrkaran
6 | RUN_MODE = prod
7 | RUN_USER = git
8 |
9 | [repository]
10 | ROOT = /data/git/repositories
11 |
12 | [repository.local]
13 | LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
14 |
15 | [repository.upload]
16 | TEMP_PATH = /data/gitea/uploads
17 |
18 | [server]
19 | APP_DATA_PATH = /data/gitea
20 | DOMAIN = git.mrkaran.dev
21 | SSH_DOMAIN = koadings.mrkaran.dev
22 | HTTP_PORT = 3000
23 | ROOT_URL = https://git.mrkaran.dev/
24 | DISABLE_SSH = false
25 | SSH_PORT = 4222
26 | SSH_LISTEN_PORT = 22
27 | LFS_START_SERVER = true
28 | LFS_CONTENT_PATH = /data/git/lfs
29 | LFS_JWT_SECRET = "${gitea_lfs_jwt_secret}"
30 | OFFLINE_MODE = true
31 | LANDING_PAGE = explore
32 |
33 | [ui]
34 | THEME_COLOR_META_TAG = "#6B46C1"
35 |
36 | [ui.meta]
37 | AUTHOR = Karan
38 | DESCRIPTION = Karan's self-hosted Gitea instance
39 | KEYWORDS = git, gitea, karan, git.mrkaran.dev, mrkaran
40 |
41 | [database]
42 | PATH = /data/gitea/gitea.db
43 | DB_TYPE = sqlite3
44 | HOST = localhost:3306
45 | NAME = gitea
46 | USER = root
47 | PASSWD =
48 | SCHEMA =
49 | SSL_MODE = disable
50 | CHARSET = utf8
51 |
52 | [indexer]
53 | ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
54 |
55 | [session]
56 | PROVIDER_CONFIG = /data/gitea/sessions
57 | PROVIDER = file
58 | COOKIE_SECURE = true
59 |
60 | [picture]
61 | AVATAR_UPLOAD_PATH = /data/gitea/avatars
62 | REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
63 | DISABLE_GRAVATAR = false
64 | ENABLE_FEDERATED_AVATAR = true
65 |
66 | [attachment]
67 | PATH = /data/gitea/attachments
68 |
69 | [log]
70 | ROOT_PATH = /data/gitea/log
71 | MODE = file
72 | LEVEL = info
73 |
74 | [security]
75 | INSTALL_LOCK = true
76 | SECRET_KEY = "${gitea_secret_key}"
77 | INTERNAL_TOKEN = "${gitea_internal_token}"
78 |
79 | [service]
80 | DISABLE_REGISTRATION = true
81 | REQUIRE_SIGNIN_VIEW = false
82 | REGISTER_EMAIL_CONFIRM = false
83 | ENABLE_NOTIFY_MAIL = false
84 | ALLOW_ONLY_EXTERNAL_REGISTRATION = false
85 | ENABLE_CAPTCHA = false
86 | DEFAULT_KEEP_EMAIL_PRIVATE = false
87 | DEFAULT_ALLOW_CREATE_ORGANIZATION = true
88 | DEFAULT_ENABLE_TIMETRACKING = true
89 | NO_REPLY_ADDRESS = noreply.localhost
90 |
91 | [oauth2]
92 | JWT_SECRET = "${gitea_oauth2_jwt_secret}"
93 |
94 | [mailer]
95 | ENABLED = false
96 |
97 | [openid]
98 | ENABLE_OPENID_SIGNIN = true
99 | ENABLE_OPENID_SIGNUP = true
100 |
101 | [metrics]
102 | ENABLED = true
103 |
104 | [cron]
105 | ENABLED = true
106 | RUN_AT_START = false
107 |
108 | [cron.archive_cleanup]
109 | RUN_AT_START = true
110 | SCHEDULE = @every 24h
111 | OLDER_THAN = 24h
112 |
113 | [cron.update_mirrors]
114 | SCHEDULE = @every 3h
115 |
116 | [cron.repo_health_check]
117 | SCHEDULE = @every 24h
118 | TIMEOUT = 60s
119 |
120 | [cron.check_repo_stats]
121 | RUN_AT_START = true
122 | SCHEDULE = @every 24h
123 |
--------------------------------------------------------------------------------
/terraform/modules/gitea/conf/gitea.nomad:
--------------------------------------------------------------------------------
1 | job "gitea" {
2 | datacenters = ["hydra"]
3 | type = "service"
4 |
5 | group "app" {
6 | count = 1
7 |
8 | network {
9 | port "http" {
10 | to = 3000
11 | }
12 |
13 | port "ssh" {
14 | to = 22
15 |
16 | # Need a static assignment for SSH ops.
17 | static = 4222
18 |
19 | # SSH port on host only exposed to Tailscale IP.
20 | host_network = "tailscale"
21 | }
22 | }
23 |
24 | restart {
25 | attempts = 2
26 | interval = "2m"
27 | delay = "30s"
28 | mode = "fail"
29 | }
30 |
31 | task "web" {
32 | driver = "docker"
33 |
34 | service {
35 | name = "gitea-web"
36 | tags = ["gitea", "web"]
37 | port = "http"
38 | }
39 |
40 | service {
41 | name = "gitea-ssh"
42 | tags = ["gitea", "ssh"]
43 | port = "ssh"
44 | }
45 |
46 | config {
47 | image = "gitea/gitea:latest"
48 |
49 | ports = ["http", "ssh"]
50 |
51 | # Bind the config file to container.
52 | mount {
53 | type = "bind"
54 | source = "local/gitea.ini"
55 | target = "/data/gitea/conf/app.ini"
56 | }
57 |
58 | # Bind the data directory to preserve data.
59 | mount {
60 | type = "bind"
61 | target = "/data"
62 | source = "/data/gitea/"
63 | readonly = false
64 | }
65 | }
66 |
67 | template {
68 | data = <