Add new Hass.io add-on: Terminal

This commit is contained in:
Franck Nijhof 2017-08-17 23:47:11 +02:00
parent 9784b670f3
commit 7f6ba84e43
No known key found for this signature in database
GPG key ID: D62583BA8AB11CA3
13 changed files with 994 additions and 1 deletions

View file

@ -54,6 +54,20 @@ focusses on security, usability and flexibility.
[:books: SSH add-on documentation](ssh)
### ✓ [Terminal](terminal)
![Latest Version][terminal-version-shield]
![Supports armhf Architecture][terminal-armhf-shield]
![Supports aarch64 Architecture][terminal-aarch64-shield]
![Supports amd64 Architecture][terminal-amd64-shield]
![Supports i386 Architecture][terminal-i386-shield]
![Docker Pulls][terminal-pulls-shield]
This add-on allows you to log in to your Hass.io Home Assistant instance using
a web terminal. It is like SSH, but in your Home Assistant frontend.
[:books: Terminal add-on documentation](terminal)
## Changelog
This add-on repository itself does not keep a change log, the individual
@ -117,10 +131,16 @@ SOFTWARE.
[maintenance-shield]: https://img.shields.io/maintenance/yes/2017.svg
[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
[semver]: http://semver.org/spec/v2.0.0.html
[third-party-addons]: https://home-assistant.io/hassio/installing_third_party_addons/
[ssh-aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[ssh-amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
[ssh-armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
[ssh-i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
[ssh-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/ssh-armhf.svg
[ssh-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/ssh-armhf.svg
[terminal-aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[terminal-amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
[terminal-armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
[terminal-i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
[terminal-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/terminal-armhf.svg
[terminal-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/terminal-armhf.svg
[third-party-addons]: https://home-assistant.io/hassio/installing_third_party_addons/

BIN
terminal/.DS_Store vendored Normal file

Binary file not shown.

14
terminal/CHANGELOG.md Normal file
View file

@ -0,0 +1,14 @@
# Hass.io Add-on Changelog: Terminal
All notable changes to this add-on will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
-
## 1.0.0 - 2017-08-16
### Added
- First version of the Terminal Add-on
- This CHANGELOG file

21
terminal/Dockerfile Executable file
View file

@ -0,0 +1,21 @@
FROM %%BASE_IMAGE%%
MAINTAINER Franck Nijhof <frenck@geekchimp.com>
# Add env
ENV LANG="C.UTF-8" \
TERM="xterm-256color"
# Copy data
COPY files/run.sh /
COPY files/hassio /usr/bin/
COPY files/motd /etc/
COPY files/.zshrc /root/
COPY files/.tmux.conf /root/
# Setup base
RUN apk add --no-cache jq openssh-client sudo zsh openssl libxml2-utils \
ncurses curl wget net-tools bind-tools rsync git nmap wget awake \
nano vim mosquitto-clients mariadb-client tmux ttyd && \
git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh && \
chmod a+x /run.sh /usr/bin/hassio
CMD [ "/run.sh" ]

248
terminal/README.md Normal file
View file

@ -0,0 +1,248 @@
# Hass.io Add-on: Terminal
![Project Stage][project-stage-shield]
![Maintenance][maintenance-shield]
![Awesome][awesome-shield]
[![License][license-shield]](LICENSE.md)
This add-on allows you to log in to your Hass.io Home Assistant instance using
a web terminal. Giving you to access your Hass.io folders and also includes a
command-line tool to do things like restart, update, and check your instance.
![Terminal in the Home Assistant Frontend](images/screenshot.png)
## Docker status
[![Docker Architecture][armhf-arch-shield]][armhf-dockerhub]
[![Docker Version][armhf-version-shield]][armhf-microbadger]
[![Docker Layers][armhf-layers-shield]][armhf-microbadger]
[![Docker Pulls][armhf-pulls-shield]][armhf-dockerhub]
[![Docker Architecture][aarch64-arch-shield]][aarch64-dockerhub]
[![Docker Version][aarch64-version-shield]][aarch64-microbadger]
[![Docker Layers][aarch64-layers-shield]][aarch64-microbadger]
[![Docker Pulls][aarch64-pulls-shield]][aarch64-dockerhub]
[![Docker Architecture][amd64-arch-shield]][amd64-dockerhub]
[![Docker Version][amd64-version-shield]][amd64-microbadger]
[![Docker Layers][amd64-layers-shield]][amd64-microbadger]
[![Docker Pulls][amd64-pulls-shield]][amd64-dockerhub]
[![Docker Architecture][i386-arch-shield]][i386-dockerhub]
[![Docker Version][i386-version-shield]][i386-microbadger]
[![Docker Layers][i386-layers-shield]][i386-microbadger]
[![Docker Pulls][i386-pulls-shield]][i386-dockerhub]
## Features
- Access your terminal right from the web!
- Add-able to your Home Assistant interface.
- Debug mode for allowing you to triage issues easier.
- Compatible if Hass.io was installed via the generic Linux installer.
- Have Alpine packages installed on start. This will allow you to install your
favorite tools, which will be available every single time you log in.
- Execute custom commands on start automatically, so you can customize the shell
to your likings.
- [ZSH][zsh] as its default shell. Easier to use for the beginner, more advanced
for the more experienced user. It even comes preloaded with
["Oh My ZSH"][ohmyzsh], with some plugins enabled as well.
- Contains a sensible set of tools right out of the box: curl, Wget, RSync, GIT,
Nmap, Mosquitto client, MariaDB/MySQL client, Awake (“wake on lan”), Nano, Vim,
tmux, and a bunch commonly used networking tools.
## Installation
The installation of this add-on is pretty straight forward and not different in
comparison to installing any other Hass.io add-on.
1. [Add our Hass.io add-ons repository][repository] to your Hass.io instance
2. Install the "Terminal" add-on from our repository
3. Start the "Terminal" add-on
4. Check the logs of the "Terminal" add-on to see if everything
went well.
5. Surf to your Hass.io instance and use port `7681` (e.g.
`http://hassio.local:7681`).
Please read the rest of this document further instructions.
## Configuration
_Please remember to restart the add-on when the configuration changes._
Example add-on configuration:
```json
{
"debug": false,
"username": "hass",
"password": "",
"ssl": true,
"certfile": "fullchain.pem",
"keyfile": "privkey.pem",
"packages": [
"python",
"python-dev",
"py-pip",
"build-base"
],
"init_commands": [
"pip install virtualenv",
"pip install yamllint"
]
}
```
_*Note*: This is just an example, don't copy and past it! Create your own!_
**Option: `debug`**
When set to `true` the addon will output more information in the logs of the
add-on. The add-on will also start the terminal server in debug mode.
This might be useful when you're dealing with an unknown issue. It is
recommended leaving to option set to `false`, unless you are troubleshooting.
**Option: `username`**
This option allows you to enable authentication on accessing the terminal.
It is only used for the authentication; you will be the `root` user after
you have authenticated. Using `root` as the username is possible, but not
recommended. Leaving it empty would disable the possibility to authentication
completely.
_*Note*: If you set an `username`, `password` becomes mandatory as well._
**Option: `password`**
Sets the password to authenticate with. Leaving it empty would disable the
possibility to authenticate completely.
_*Note*: If you set a `password`, `username` becomes mandatory as well._
**Option: `ssl`**
Enables/Disables SSL (HTTPS) on the web terminal. Set it `true` to enable it,
`false` otherwise.
**Option: `certfile`**
The certificate file to use for SSL.
_*Note*: The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Option: `keyfile`**
The private key file to use for SSL.
_*Note*: The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Option: `packages`**
Allows you to specify additional [Alpine packages][alpine-packages] to be
installed in your shell environment (e.g. Python, Joe, Irssi).
_*Note*: Adding many packages will result in a longer start-up
time for the add-on._
**Option: `init_commands`**
Customize your terminal environment even more with the `init_commands` option.
Add one or more shell commands to the list, and they will be executed every
single time this add-on starts.
## Embedding into Home Assistant
It is possible to embed the terminal directly into Home Assistant, allowing
you to access your terminal through the Home Assistant frontend.
Home Assistant provides the `panel_iframe` component, for these purposes.
Example configuration:
```yaml
panel_iframe:
terminal:
title: Terminal
icon: mdi:console
url: https://addres.to.your.hass.io:7681
```
## Support
Got questions? Got some unexpected behavior caused by this plugin?
Please [open an issue on our GitHub repository][issues] and we'll do our best
to help you out.
## Credits
A big shout out to the following people, without them this add-on wasn't possible:
- The team & community of [Home Assistant][home-assistant] for developing such an
excellent home automation toolkit
Thank you all!
## More Hass.io add-ons
Do you like this add-on? Want some more functionality to your Hass.io Home
Assistant instance?
We've created multiple add-ons for Hass.io. For a full list, check out
our [GitHub Repository][repository].
## License
MIT License
Copyright (c) 2017 Franck Nijhof
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[aarch64-arch-shield]: https://img.shields.io/badge/architecture-aarch64-blue.svg
[aarch64-dockerhub]: https://hub.docker.com/r/hassioaddons/terminal-aarch64
[aarch64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/terminal-aarch64.svg
[aarch64-microbadger]: https://microbadger.com/images/hassioaddons/terminal-aarch64
[aarch64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/terminal-aarch64.svg
[aarch64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/terminal-aarch64.svg
[alpine-packages]: https://pkgs.alpinelinux.org/packages
[amd64-arch-shield]: https://img.shields.io/badge/architecture-amd64-blue.svg
[amd64-dockerhub]: https://hub.docker.com/r/hassioaddons/terminal-amd64
[amd64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/terminal-amd64.svg
[amd64-microbadger]: https://microbadger.com/images/hassioaddons/terminal-amd64
[amd64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/terminal-amd64.svg
[amd64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/terminal-amd64.svg
[armhf-arch-shield]: https://img.shields.io/badge/architecture-armhf-blue.svg
[armhf-dockerhub]: https://hub.docker.com/r/hassioaddons/terminal-armhf
[armhf-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/terminal-armhf.svg
[armhf-microbadger]: https://microbadger.com/images/hassioaddons/terminal-armhf
[armhf-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/terminal-armhf.svg
[armhf-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/terminal-armhf.svg
[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg
[home-assistant]: https://home-assistant.io
[i386-arch-shield]: https://img.shields.io/badge/architecture-i386-blue.svg
[i386-dockerhub]: https://hub.docker.com/r/hassioaddons/terminal-i386
[i386-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/terminal-i386.svg
[i386-microbadger]: https://microbadger.com/images/hassioaddons/terminal-i386
[i386-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/terminal-i386.svg
[i386-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/terminal-i386.svg
[issues]: https://github.com/hassio-addons/repository/issues
[license-shield]: https://img.shields.io/github/license/hassio-addons/repository.svg
[maintenance-shield]: https://img.shields.io/maintenance/yes/2017.svg
[ohmyzsh]: http://ohmyz.sh/
[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
[repository]: https://github.com/hassio-addons/repository
[zsh]: https://en.wikipedia.org/wiki/Z_shell

43
terminal/config.json Executable file
View file

@ -0,0 +1,43 @@
{
"name": "Terminal",
"version": "1.0.0",
"slug": "ssh",
"description": "Terminal access to your Home Assistant instance via the web",
"url": "https://github.com/hassio-addons/repository/tree/master/terminal",
"webui": "http://[HOST]:[PORT:7681]",
"startup": "services",
"boot": "auto",
"ports": {
"7681/tcp": 7681
},
"host_network": false,
"hassio_api": true,
"map": [
"config:rw",
"ssl:rw",
"addons:rw",
"share:rw",
"backup:rw"
],
"options": {
"debug": false,
"username": "",
"password": "",
"ssl": false,
"certfile": "fullchain.pem",
"keyfile": "privkey.pem",
"packages": [],
"init_commands": []
},
"schema": {
"debug": "bool",
"username": "str",
"password": "str",
"ssl": "bool",
"certfile": "str",
"keyfile": "str",
"packages": ["str"],
"init_commands": ["str"]
},
"image": "hassioaddons/terminal-{arch}"
}

23
terminal/files/.tmux.conf Normal file
View file

@ -0,0 +1,23 @@
set-option -g default-shell /bin/zsh
set-option -g default-terminal $TERM
set-option -g base-index 1
setw -g pane-base-index 1
setw -g window-status-format "#[fg=white]#[bg=blue] #I #[bg=blue]#[fg=white] #W "
setw -g window-status-current-format "#[bg=brightmagenta]#[fg=white] *#I #[fg=white,bold]#[bg=cyan] [#W] "
set -g pane-border-fg black
set -g pane-active-border-fg blue
set -g status-fg white
set -g status-bg blue
set -g status-left ''
set -g status-right '%a %m-%d %H:%M'
unbind C-b
set-option -g prefix C-a
bind-key C-a send-prefix
bind | split-window -h
bind - split-window -v
unbind '"'
unbind %
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

88
terminal/files/.zshrc Executable file
View file

@ -0,0 +1,88 @@
# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH
# Path to your oh-my-zsh installation.
export ZSH=$HOME/.oh-my-zsh
# Set name of the theme to load. Optionally, if you set this to "random"
# it'll load a random theme each time that oh-my-zsh is loaded.
# See https://github.com/robbyrussell/oh-my-zsh/wiki/Themes
ZSH_THEME="robbyrussell"
# Uncomment the following line to use case-sensitive completion.
# CASE_SENSITIVE="true"
# Uncomment the following line to use hyphen-insensitive completion. Case
# sensitive completion must be off. _ and - will be interchangeable.
# HYPHEN_INSENSITIVE="true"
# Uncomment the following line to disable bi-weekly auto-update checks.
DISABLE_AUTO_UPDATE="true"
# Uncomment the following line to change how often to auto-update (in days).
# export UPDATE_ZSH_DAYS=13
# Uncomment the following line to disable colors in ls.
# DISABLE_LS_COLORS="true"
# Uncomment the following line to disable auto-setting terminal title.
# DISABLE_AUTO_TITLE="true"
# Uncomment the following line to enable command auto-correction.
# ENABLE_CORRECTION="true"
# Uncomment the following line to display red dots whilst waiting for completion.
COMPLETION_WAITING_DOTS="true"
# Uncomment the following line if you want to disable marking untracked files
# under VCS as dirty. This makes repository status check for large repositories
# much, much faster.
# DISABLE_UNTRACKED_FILES_DIRTY="true"
# Uncomment the following line if you want to change the command execution time
# stamp shown in the history command output.
# The optional three formats: "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
# HIST_STAMPS="mm/dd/yyyy"
# Would you like to use another custom folder than $ZSH/custom?
# ZSH_CUSTOM=/path/to/new-custom-folder
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(extract git tmux nmap rsync)
source $ZSH/oh-my-zsh.sh
# User configuration
# export MANPATH="/usr/local/man:$MANPATH"
# You may need to manually set your language environment
# export LANG=en_US.UTF-8
# Preferred editor for local and remote sessions
# if [[ -n $SSH_CONNECTION ]]; then
# export EDITOR='vim'
# else
# export EDITOR='mvim'
# fi
# Compilation flags
# export ARCHFLAGS="-arch x86_64"
# ssh
# export SSH_KEY_PATH="~/.ssh/rsa_id"
# Set personal aliases, overriding those provided by oh-my-zsh libs,
# plugins, and themes. Aliases can be placed here, though oh-my-zsh
# users are encouraged to define aliases within the ZSH_CUSTOM folder.
# For a full list of active aliases, run `alias`.
#
# Example aliases
# alias zshconfig="mate ~/.zshrc"
# alias ohmyzsh="mate ~/.oh-my-zsh"
# Show motd on start
cat /etc/motd

101
terminal/files/hassio Executable file
View file

@ -0,0 +1,101 @@
#!/bin/bash
set -e
# helppage
if [ "$1" == "help" ] || [ "$#" -lt 2 ]; then
cat << EOF
---- Hass.IO Cli ----
HomeAssistant:
$ hassio homeassistant logs
$ hassio homeassistant restart
$ hassio homeassistant update
$ hassio homeassistant check
Host:
$ hassio host hardware
$ hassio host reboot
$ hassio host shutdown
$ hassio host update
Supervisor
$ hassio supervisor logs
$ hassio supervisor info
$ hassio supervisor reload
$ hassio supervisor update
EOF
fi
function call_api() {
get_cmd=('info' 'logs' 'hardware')
command='POST'
if [[ ${get_cmd[*]} =~ $2 ]]; then
command='GET'
fi
if ! api_ret="$(curl -s -X $command "http://hassio/$1/$2")"; then
echo "API error: $api_ret"
return 1
fi
if [ "$2" == "logs" ]; then
echo "$api_ret"
return 0
fi
result="$(echo "$api_ret" | jq --raw-output ".result")"
# On error
if [ "$result" == "error" ]; then
message="$(echo "$api_ret" | jq --raw-output ".message // empty")"
echo "Error on $1/$2:" "$message"
return 0
fi
# On success
data="$(echo "$api_ret" | jq 'if .data == {} then empty else .data end')"
if [ ! -z "$data" ]; then
echo "$data" | jq .
else
echo "Success $1/$2"
fi
return 0
}
######
# homeassistant functions
if [ "$1" == "homeassistant" ]; then
hass_cmd=('logs' 'restart' 'update' 'check')
if [[ ! ${hass_cmd[*]} =~ $2 ]]; then
echo "No homeassistant command '$2' found!"
exit 1
fi
call_api "$1" "$2"
fi
######
# host functions
if [ "$1" == "host" ]; then
hass_cmd=('reboot' 'shutdown' 'update' 'hardware')
if [[ ! ${hass_cmd[*]} =~ $2 ]]; then
echo "No host command '$2' found!"
exit 1
fi
call_api "$1" "$2"
fi
######
# supervisor functions
if [ "$1" == "supervisor" ]; then
hass_cmd=('logs' 'reload' 'update' 'info')
if [[ ! ${hass_cmd[*]} =~ $2 ]]; then
echo "No supervisor command '$2' found!"
exit 1
fi
call_api "$1" "$2"
fi

12
terminal/files/motd Executable file
View file

@ -0,0 +1,12 @@
_ _ _____ ____
| | | | |_ _/ __ \
| |__| | __ _ ___ ___ | || | | |
| __ |/ _` / __/ __| | || | | |
| | | | (_| \__ \__ \_ _| || |__| |
|_| |_|\__,_|___/___(_)_____\____/
Our Cli:
$ hassio help

423
terminal/files/run.sh Executable file
View file

@ -0,0 +1,423 @@
#!/usr/bin/env bash
# ==============================================================================
# Hass.io Add-on for Home Assistant: Terminal
# ==============================================================================
set -o errexit # Exit script when a command exits with non-zero status
set -o nounset # Exit script on use of an undefined variable
set -o pipefail # Return exit status of the last command in the pipe that failed
# ==============================================================================
# GLOBALS
# ==============================================================================
# Exit codes
readonly EX_OK=0 # Successful termination
readonly EX_NO_USERNAME=3 # No username specified in configuration
readonly EX_NO_PASSWORD=4 # No login data in user configuration
readonly EX_NO_CERTFILE=5 # SSL enabled, but no certfile configured
readonly EX_NO_KEYFILE=6 # SSL enabled, but no keyfile configured
readonly EX_CERTFILE_NOT_FOUND=7 # Specified certfile was not found
readonly EX_KEYFILE_NOT_FOUND=8 # Specified keyfile was not found
readonly EX_COMMON_LINK=10 # Failed to link common directory
readonly EX_APK_UPDATE=11 # Alpine update failed
readonly EX_PACKAGE_FAILED=12 # Alpine package installation failed
readonly EX_INIT_COMMAND=13 # Failed executing custom init command
# Configuration paths
readonly CONFIG_PATH=/data/options.json
# Shell history files
readonly ZSH_HISTORY_FILE=/root/.zsh_history
readonly ZSH_HISTORY_PERSISTANT_FILE=/data/.zsh_history
# SSL certificates base path
readonly SSL_CERT_PATH=/ssl
# Debug mode?
readonly DEBUG=$(jq --raw-output ".debug" $CONFIG_PATH)
# Arguments to pass into ttyd
readonly TTYD_DEFAULTS='--reconnect 30 --port 7681'
readonly TTYD_COMMAND='tmux new -A -s ttyd zsh'
export TTYD_SSL=''
export TTYD_CREDENTIALS=''
# ==============================================================================
# UTILITY
# ==============================================================================
# ------------------------------------------------------------------------------
# Displays a status message
# Globals:
# None
# Arguments:
# $* Status message to display
# Returns:
# None
# ------------------------------------------------------------------------------
display_status_message() {
local status=$*
echo "[ADD-ON] $status"
}
# ------------------------------------------------------------------------------
# Displays a debug message
# Globals:
# None
# Arguments:
# $* Status message to display
# Returns:
# None
# ------------------------------------------------------------------------------
display_debug_message() {
local status=$*
if [[ "$DEBUG" == "true" ]];
then
display_status_message "[DEBUG] $status"
fi
}
# ------------------------------------------------------------------------------
# Displays a error message and is able to terminate te script execution
# Globals:
# None
# Arguments:
# $1 Error message
# $2 Exitcode, script will continue execution when omitted
# Returns:
# None
# ------------------------------------------------------------------------------
display_error_message() {
local status=$1
local exitcode=${2:-0}
echo "[ADD-ON][ERROR] An error occured!" >&2
echo >&2
echo "!!! ERROR: $status" >&2
echo >&2
if [[ $exitcode -ne 0 ]];
then
exit "$exitcode"
fi
}
# ------------------------------------------------------------------------------
# Gets a configuration parameter form the configuration file
# Globals:
# CONFIG_PATH
# Arguments:
# $1 Key of the configuration parameter to get
# $2 'true' If the configuration value is an array, false otherwise
# Returns:
# The configuration value
# ------------------------------------------------------------------------------
get_config() {
local key=$1
local is_array=$2
if $is_array;
then
command jq --raw-output ".$key[]" $CONFIG_PATH
else
command jq --raw-output ".$key" $CONFIG_PATH
fi
}
# ==============================================================================
# SCRIPT LOGIC
# ==============================================================================
# ------------------------------------------------------------------------------
# Ensures user configuration contains required parameters
# Globals:
# EX_CERTFILE_NOT_FOUND
# EX_KEYFILE_NOT_FOUND
# EX_NO_CERTFILE
# EX_NO_KEYFILE
# EX_NO_PASSWORD
# EX_NO_USERNAME
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
ensure_config_requirements() {
local password
local username
local ssl
local certfile
local keyfile
display_status_message 'Ensuring configuration requirements are met'
username=$(get_config 'username' false)
password=$(get_config 'password' false)
if [[ ! -z "$username" ]] && [[ -z "$password" ]];
then
display_error_message \
'You have set an username, but no password!' "$EX_NO_PASSWORD"
fi
if [[ -z "$username" ]] && [[ ! -z "$password" ]];
then
display_error_message \
'You have set a password, but not username!' "$EX_NO_USERNAME"
fi
ssl=$(get_config 'ssl' false)
if [[ "$ssl" == "true" ]];
then
certfile=$(get_config 'certfile' false)
if [[ -z "$certfile" ]];
then
display_error_message 'SSL is enabled, but no certfile was specified' \
"$EX_NO_CERTFILE"
fi
if [[ ! -f "$SSL_CERT_PATH/$certfile" ]];
then
display_error_message 'The configured certfile is not found' \
"$EX_CERTFILE_NOT_FOUND"
fi
keyfile=$(get_config 'keyfile' false)
if [[ -z "$keyfile" ]];
then
display_error_message 'SSL is enabled, but no keyfile was specified' \
"$EX_NO_KEYFILE"
fi
if [[ ! -f "$SSL_CERT_PATH/$keyfile" ]];
then
display_error_message 'The configured keyfile is not found' \
"$EX_KEYFILE_NOT_FOUND"
fi
fi
}
# ------------------------------------------------------------------------------
# Sets up basic HTTP authentication
# Globals:
# None
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
setup_credentials() {
local password
local username
password=$(get_config 'password' false)
username=$(get_config 'username' false)
if [[ ! -z "$username" ]] && [[ ! -z "$password" ]];
then
display_status_message 'Setting up and enabling authentication'
export TTYD_CREDENTIALS="--credential $username:$password"
fi
}
# ------------------------------------------------------------------------------
# Sets up SSL connections
# Globals:
# SSL_CERT_PATH
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
setup_ssl() {
local ssl
local certfile
local keyfile
local options
ssl=$(get_config 'ssl' false)
if [[ "$ssl" == "true" ]];
then
display_status_message 'Setting up and enabling SSL'
certfile=$(get_config 'certfile' false)
keyfile=$(get_config 'keyfile' false)
options='--ssl '
options+=" --ssl-cert $SSL_CERT_PATH/$certfile"
options+=" --ssl-key $SSL_CERT_PATH/$keyfile"
export TTYD_SSL="$options"
fi
}
# ------------------------------------------------------------------------------
# Link a set of common used directories in the home folder
# Globals:
# EX_COMMON_LINK
# HOME
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
link_common_directories() {
local directories
display_status_message 'Linking common directories into the home folder'
directories="addons backup config share ssl"
for dir in $directories;
do
display_debug_message "Linking common directory $dir"
command ln -s "/$dir" "$HOME/$dir" || display_error_message \
"Failed linking common directory: $dir" "$EX_COMMON_LINK"
done;
}
# ------------------------------------------------------------------------------
# Persist all shell history in the permanent data storage directory
# Globals:
# ZSH_HISTORY_FILE
# ZSH_HISTORY_PERSISTANT_FILE
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
persist_shell_history() {
display_status_message 'Configuring shell to persist history'
command touch "$ZSH_HISTORY_PERSISTANT_FILE"
command chmod 600 "$ZSH_HISTORY_PERSISTANT_FILE"
command ln -s -f "$ZSH_HISTORY_PERSISTANT_FILE" "$ZSH_HISTORY_FILE"
}
# ------------------------------------------------------------------------------
# Install list of user requested Alpine packages
# Globals:
# EX_APK_UPDATE
# EX_PACKAGE_FAILED
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
install_packages() {
local packages
packages=$(get_config 'packages' true)
if [[ ! -z "$packages" ]];
then
display_status_message 'Installing user requested Alpine packages'
display_status_message 'Updating Alpine packages repository indexes'
command apk update || display_error_message \
'Failed updating Alpine packages repository indexes' "$EX_APK_UPDATE"
for package in $packages;
do
display_status_message "Installing Alpine package: $package"
command apk add "$package" || display_error_message \
"Failed installing package $package" $EX_PACKAGE_FAILED
done
fi
}
# ------------------------------------------------------------------------------
# Runs configured custom commands on startup of the add-on
# Globals:
# EX_INIT_COMMAND
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
run_init_commands() {
local commands
commands=$(get_config 'init_commands' true)
if [[ ! -z "$commands" ]];
then
display_status_message 'Running custom init commands'
while read -r cmd;
do
display_debug_message "Running command: $cmd"
eval "$cmd" || display_error_message \
"Failed executing init command: $cmd" "$EX_INIT_COMMAND"
done <<< "$commands"
else
display_debug_message 'No custom init commands configured'
fi
}
# ------------------------------------------------------------------------------
# Starts the SSH daemon
# Globals:
# DEBUG
# TTYD_COMMAND
# TTYD_CREDENTIALS
# TTYD_DEFAULTS
# TTYD_SSL
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
start_terminal_server() {
display_status_message 'Starting terminal server'
if [[ "$DEBUG" == "true" ]];
then
command ttyd -d 7 $TTYD_DEFAULTS $TTYD_CREDENTIALS $TTYD_SSL $TTYD_COMMAND
else
command ttyd -d 1 $TTYD_DEFAULTS $TTYD_CREDENTIALS $TTYD_SSL $TTYD_COMMAND
fi
}
# ------------------------------------------------------------------------------
# Cleanup function after execution is of the script is stopped. (trap)
# Globals:
# None
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
cleanup() {
true
}
# ==============================================================================
# RUN LOGIC
# ------------------------------------------------------------------------------
# Globals:
# EX_OK
# HOMEBRIDGE_CONFIG_FILE
# Arguments:
# None
# Returns:
# None
# ------------------------------------------------------------------------------
main() {
trap cleanup ERR
trap cleanup EXIT
ensure_config_requirements
link_common_directories
persist_shell_history
install_packages
run_init_commands
setup_credentials
setup_ssl
start_terminal_server
exit "$EX_OK"
}
main

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
terminal/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB