🔨 Full rewrite onto new base and S6

This commit is contained in:
Franck Nijhof 2017-10-20 12:58:01 +02:00
parent 7e5eb855d7
commit 40b009dd3a
No known key found for this signature in database
GPG key ID: D62583BA8AB11CA3
24 changed files with 413 additions and 534 deletions

View file

@ -1,4 +1,4 @@
## Problem/Motivation
# Problem/Motivation
> (Why the issue was filed)
@ -16,4 +16,5 @@
## Proposed changes
> (If you have a proposed change, workaround or fix, describe the rationale behind it)
> (If you have a proposed change, workaround or fix,
> describe the rationale behind it)

View file

@ -1,7 +1,9 @@
## Proposed Changes
# Proposed Changes
> (Describe the changes and rationale behind them)
## Related Issues
> ([Github link](https://help.github.com/articles/autolinked-references-and-urls/) to related issues or pull requests)
> ([Github link][autolink-references] to related issues or pull requests)
[autolink-references]: https://help.github.com/articles/autolinked-references-and-urls/

View file

@ -6,9 +6,25 @@ 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
-
### Added
- Added CodeClimate
- Added CircleCI
- Added support for hass.io's extended label schema
- Added persistency of the ~/.ssh folder
### Changed
- Migrated to the new Hass.io build system
- Migrated to our new base images
- Rewrite of add-on onto the S6 process supervisor
- Upgraded the hassio CLI tool to the latest version
- Updated documentation
## 1.0.0 - 2017-08-16
### Added
- First version of the Terminal Add-on
- This CHANGELOG file

View file

@ -22,11 +22,14 @@ include:
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- The use of sexualized language or imagery and unwelcome sexual attention
or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
- Publishing others' private information, such as a physical or
electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate
in a professional setting
## Our responsibilities
@ -52,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project lead at frenck@geekchimp.com. All
reported by contacting the project lead at frenck@addons.community. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project lead is
obligated to maintain confidentiality with regard to the reporter of an incident.

View file

@ -21,9 +21,9 @@ Even better: You could submit a pull request with a fix / new feature!
1. Search our repository for open or closed [pull requests][prs] that relates
to your submission. You don't want to duplicate effort.
2. You may merge the pull request in once you have the sign-off of two other
1. You may merge the pull request in once you have the sign-off of two other
developers, or if you do not have permission to do that, you may request
the second reviewer to merge it for you.
[github]: https://github.com/hassio-addons/addon-terminal/issues
[prs]: https://github.com/hassio-addons/addon-terminal/pulls
[prs]: https://github.com/hassio-addons/addon-terminal/pulls

238
README.md
View file

@ -1,16 +1,66 @@
# Community Hass.io Add-on: Terminal
# Community Hass.io Add-ons: Terminal
[![GitHub Release][releases-shield]][releases]
![Project Stage][project-stage-shield]
![Maintenance][maintenance-shield]
![Awesome][awesome-shield]
![Project Maintenance][maintenance-shield]
[![GitHub Activity][commits-shield]][commits]
[![License][license-shield]](LICENSE.md)
[![CircleCI][circleci-shield]][circleci]
[![Code Climate][codeclimate-shield]][codeclimate]
[![Bountysource][bountysource-shield]][bountysource]
[![Discord][discord-shield]][discord]
[![Community Forum][forum-shield]][forum]
[![Gratipay][gratipay-shield]][gratipay]
[![Patreon][patreon-shield]][patreon]
[![PayPal][paypal-shield]][paypal]
[![Bitcoin][bitcoin-shield]][bitcoin]
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.
a web terminal.
## About
This add-on allows you to log in to your Hass.io Home Assistant instance using
a web terminal. Giving you to access your Home Assistant configuration file and
folder, 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)
## 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 that 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 straightforward 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.
1. Install the "Terminal" add-on.
1. Start the "Terminal" add-on
1. Check the logs of the "Terminal" add-on to see if everything went well.
1. Surf to your Hass.io instance and use port `7681`
(e.g. `http://hassio.local:7681`).
**NOTE**: Do not add this repository to Hass.io, please use:
`https://github.com/hassio-addons/repository`.
## Docker status
[![Docker Architecture][armhf-arch-shield]][armhf-dockerhub]
@ -33,48 +83,16 @@ command-line tool to do things like restart, update, and check your instance.
[![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 that 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.
**NOTE**: Do not add this repository, but use:
`https://github.com/hassio-addons/repository`.
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._
**Note**: _Remember to restart the add-on when the configuration is changed._
Example add-on configuration:
```json
{
"debug": false,
"username": "hass",
"log_level": "info",
"username": "hassio",
"password": "changeme",
"ssl": true,
"certfile": "fullchain.pem",
@ -91,17 +109,30 @@ Example add-on configuration:
]
}
```
_*Note*: This is just an example, don't copy and past it! Create your own!_
**Option: `debug`**
**Note**: _This is just an example, don't copy and past it! Create your own!_
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.
### Option: `log_level`
This might be useful when you are dealing with an unknown issue. It is
recommended leaving to option set to `false`, unless you are troubleshooting.
The `log_level` option controls the level of log output by the addon and can
be changed to be more or less verbose, which might be useful when you are
dealing with an unknown issue. Possible values are:
**Option: `username`**
- `trace`: Show every detail, like all called internal functions.
- `debug`: Shows detailed debug information.
- `info`: Normal (usually) interesting events.
- `warning`: Exceptional occurrences that are not errors.
- `error`: Runtime errors that do not require immediate action.
- `fatal`: Something went terribly wrong. Add-on becomes unusable.
Please note that each level automatically includes log messages from a
more severe level, e.g., `debug` also shows `info` messages. By default,
the `log_level` is set to `info`, which is the recommended setting unless
you are troubleshooting.
Using `trace` or `debug` log levels puts the terminal daemon into debug mode.
### 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
@ -109,49 +140,49 @@ 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._
**Note**: _If you set an `username`, `password` becomes mandatory as well._
**Option: `password`**
### 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._
**Note**: _If you set a `password`, `username` becomes mandatory as well._
**Option: `ssl`**
### Option: `ssl`
Enables/Disables SSL (HTTPS) on the web terminal. Set it `true` to enable it,
`false` otherwise.
**Option: `certfile`**
### Option: `certfile`
The certificate file to use for SSL.
_*Note*: The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Note**: _The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Option: `keyfile`**
### Option: `keyfile`
The private key file to use for SSL.
_*Note*: The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Note**: _The file MUST be stored in `/ssl/`, which is default for Hass.io_
**Option: `packages`**
### Option: `packages`
Allows you to specify additional [Alpine packages][alpine-packages] to be
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
**Note**: _Adding many packages will result in a longer start-up
time for the add-on._
**Option: `init_commands`**
### 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.
single time this add-on starts.
## Embedding into Home Assistant
It is possible to embed the terminal directly into Home Assistant, allowing
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.
@ -166,27 +197,53 @@ panel_iframe:
url: https://addres.to.your.hass.io:7681
```
## Changelog & Releases
This repository keeps a [change log](CHANGELOG.md). The format of the log
is based on [Keep a Changelog][keepchangelog].
Releases are based on [Semantic Versioning][semver], and use the format
of ``MAJOR.MINOR.PATCH``. In a nutshell, the version will be incremented
based on the following:
- ``MAJOR``: Incompatible or major changes.
- ``MINOR``: Backwards-compatible new features and enhancements.
- ``PATCH``: Backwards-compatible bugfixes and package updates.
## Support
Got questions? Got some unexpected behavior caused by this plugin?
Got questions?
Please [open an issue on our GitHub repository][issues] and we will do our best
to help you out.
You have several options to get them answered:
## Credits
- The Home Assistant [Community Forum][forum], we have a
[dedicated topic][forum] on that forum regarding this repository.
- The Home Assistant [Discord Chat Server][discord] for general Home Assistant
discussions and questions.
- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
A big shout out to the following people, without them this add-on was not
possible:
You could also [open an issue here][issue] GitHub.
- The team & community of [Home Assistant][home-assistant] for developing such
an excellent home automation toolkit
## Contributing
Thank you all!
This is an active open-source project. We are always open to people who want to
use the code or contribute to it.
## More Hass.io add-ons
We have set up a separate document containing our
[contribution guidelines](CONTRIBUTING.md).
Do you like this add-on? Want some more functionality to your Hass.io Home
Assistant instance?
Thank you for being involved! :heart_eyes:
## Authors & contributors
The original setup of this repository is by [Franck Nijhof][frenck].
For a full list of all authors and contributors,
check [the contributor's page][contributors].
## We have got some Hass.io add-ons for you
Want some more functionality to your Hass.io Home Assistant instance?
We have created multiple add-ons for Hass.io. For a full list, check out
our [GitHub Repository][repository].
@ -234,7 +291,23 @@ SOFTWARE.
[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
[bitcoin-shield]: https://img.shields.io/badge/donate-bitcoin-blue.svg
[bitcoin]: https://blockchain.info/payment_request?address=3GVzgN6NpVtfXnyg5dQnaujtqVTEDBCtAH
[bountysource-shield]: https://img.shields.io/bountysource/team/hassio-addons/activity.svg
[bountysource]: https://www.bountysource.com/teams/hassio-addons/issues
[circleci-shield]: https://img.shields.io/circleci/project/github/hassio-addons/addon-terminal.svg
[circleci]: https://circleci.com/gh/hassio-addons/addon-terminal
[codeclimate-shield]: https://img.shields.io/badge/code%20climate-protected-brightgreen.svg
[codeclimate]: https://codeclimate.com/github/hassio-addons/addon-terminal
[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-terminal.svg
[commits]: https://github.com/hassio-addons/addon-terminal/commits/master
[discord-shield]: https://img.shields.io/discord/330944238910963714.svg
[discord]: https://discord.gg/c5DvZ4e
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg
[forum]: https://community.home-assistant.io/t/repository-community-hass-io-add-ons/24705?u=frenck
[frenck]: https://github.com/frenck
[gratipay-shield]: https://img.shields.io/badge/donate-gratipay-blue.svg
[gratipay]: https://gratipay.com/hassio-addons/
[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
@ -242,10 +315,19 @@ SOFTWARE.
[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/addon-terminal/issues
[issue]: https://github.com/hassio-addons/addon-terminal/issues
[keepchangelog]: http://keepachangelog.com/en/1.0.0/
[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-terminal.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
[patreon-shield]: https://img.shields.io/badge/donate-patreon-blue.svg
[patreon]: https://www.patreon.com/frenck
[paypal-shield]: https://img.shields.io/badge/donate-paypal-blue.svg
[paypal]: https://www.paypal.me/FranckNijhof
[project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg
[reddit]: https://reddit.com/r/homeassistant
[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-terminal.svg
[releases]: https://github.com/hassio-addons/addon-terminal/releases
[repository]: https://github.com/hassio-addons/repository
[zsh]: https://en.wikipedia.org/wiki/Z_shell
[semver]: http://semver.org/spec/v2.0.0.htm
[zsh]: https://en.wikipedia.org/wiki/Z_shell

View file

@ -1,5 +1,5 @@
{
"name": "Development - Community Hass.io add-on: Terminal",
"name": "Development - Community Hass.io Add-ons: Terminal",
"url": "https://github.com/hassio-addons/addon-terminal",
"maintainer": "Franck Nijhof <frenck@geekchimp.com>"
"maintainer": "Franck Nijhof <frenck@addons.community>"
}

View file

@ -5,21 +5,33 @@ FROM ${BUILD_FROM}
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/
# Copy root filesystem
COPY rootfs /
# 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" ]
RUN \
apk add --no-cache \
awake \
bind-tools \
git \
libxml2-utils \
mariadb-client \
mosquitto-clients \
nano \
ncurses \
net-tools \
nmap \
openssh-client \
openssl \
rsync \
sudo \
tmux \
ttyd \
vim \
wget \
zsh \
\
&& git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
# Build arugments
ARG BUILD_ARCH
@ -43,4 +55,4 @@ LABEL \
org.label-schema.usage="https://github.com/hassio-addons/addon-terminal/tree/master/README.md" \
org.label-schema.vcs-ref=${BUILD_REF} \
org.label-schema.vcs-url="https://github.com/hassio-addons/addon-terminal" \
org.label-schema.vendor="Community Hass.io Add-ons"
org.label-schema.vendor="Community Hass.io Add-ons"

10
terminal/build.json Normal file
View file

@ -0,0 +1,10 @@
{
"squash": false,
"build_from": {
"aarch64": "hassioaddons/base-aarch64:1.0.0",
"amd64": "hassioaddons/base-amd64:1.0.0",
"armhf": "hassioaddons/base-armhf:1.0.0",
"i386": "hassioaddons/base-i386:1.0.0"
},
"args": {}
}

View file

@ -1,17 +1,18 @@
{
"name": "Terminal",
"version": "1.0.0",
"version": "dev",
"slug": "terminal",
"description": "Terminal access to your Home Assistant instance via the web",
"url": "https://github.com/hassio-addons/addon-terminal",
"webui": "http://[HOST]:[PORT:7681]",
"startup": "services",
"boot": "auto",
"hassio_api": true,
"homeassistant_api": true,
"host_network": false,
"ports": {
"7681/tcp": 7681
},
"host_network": false,
"hassio_api": true,
"map": [
"config:rw",
"ssl:rw",
@ -20,7 +21,7 @@
"backup:rw"
],
"options": {
"debug": false,
"log_level": "info",
"username": "",
"password": "",
"ssl": false,
@ -30,7 +31,7 @@
"init_commands": []
},
"schema": {
"debug": "bool",
"log_level": "match(^(trace|debug|info|notice|warning|error|fatal)$)",
"username": "str",
"password": "str",
"ssl": "bool",
@ -38,5 +39,8 @@
"keyfile": "str",
"packages": ["str"],
"init_commands": ["str"]
},
"environment": {
"LOG_FORMAT": "{LEVEL}: {MESSAGE}"
}
}

View file

@ -1,423 +0,0 @@
#!/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

View file

@ -0,0 +1,35 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# This files check if all user configuration requirements are met
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
# Check if username password as set together
if hass.config.has_value 'username' && ! hass.config.has_value 'password'; then
hass.die 'You have set an username, but no password!'
fi
if ! hass.config.has_value 'username' && hass.config.has_value 'password'; then
hass.die 'You have set a password, but no username!'
fi
# Check SSL requirements, if enabled
if hass.config.true 'ssl'; then
if ! hass.config.has_value 'certfile'; then
hass.die 'SSL is enabled, but no certfile was specified'
fi
if ! hass.config.has_value 'keyfile'; then
hass.die 'SSL is enabled, but no keyfile was specified'
fi
if ! hass.file_exists "/ssl/$(hass.config.get 'certfile')"; then
hass.die 'The configured certfile is not found'
fi
if ! hass.file_exists "/ssl/$(hass.config.get 'keyfile')"; then
hass.die 'The configured keyfile is not found'
fi
fi

View file

@ -0,0 +1,14 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Links some common directories to the user's home folder for convenience
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
readonly -a directories=(addons backup config share ssl)
for dir in "${directories[@]}"; do
ln -s "/${dir}" "${HOME}/${dir}" \
|| hass.log.warning "Failed linking common directory: ${dir}"
done

View file

@ -0,0 +1,19 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Sets up ZSH shell
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
readonly ZSH_HISTORY_FILE=/root/.zsh_history
readonly ZSH_HISTORY_PERSISTANT_FILE=/data/.zsh_history
touch "${ZSH_HISTORY_PERSISTANT_FILE}" \
|| hass.die 'Failed creating a persistent ZSH history file'
chmod 600 "$ZSH_HISTORY_PERSISTANT_FILE" \
|| hass.die 'Failed setting the correct permissions to the ZSH history file'
ln -s -f "$ZSH_HISTORY_PERSISTANT_FILE" "$ZSH_HISTORY_FILE" \
|| hass.die 'Failed linking the persistant ZSH history file'

View file

@ -0,0 +1,19 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Sets up the users .ssh folder to be persistent
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
readonly SSH_USER_PATH=/data/.ssh
if ! hass.directory_exists "${SSH_USER_PATH}"; then
mkdir -p "${SSH_USER_PATH}" \
|| hass.die 'Failed to create a persistent .ssh folder'
chmod 700 "${SSH_USER_PATH}" \
|| hass.die 'Failed setting permissions on persistent .ssh folder'
fi
ln -s "${SSH_USER_PATH}" ~/.ssh

View file

@ -0,0 +1,17 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Install user configured/requested packages
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
if hass.config.has_value 'packages'; then
apk update \
|| hass.die 'Failed updating Alpine packages repository indexes'
for package in $(hass.config.get 'packages'); do
apk add "$package" \
|| hass.die "Failed installing package ${package}"
done
fi

View file

@ -0,0 +1,14 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Executes user configured/requested commands on startup
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
if hass.config.has_value 'init_commands'; then
while read -r cmd; do
eval "${cmd}" \
|| hass.die "Failed executing init command: ${cmd}"
done <<< "$(hass.config.get 'init_commands')"
fi

View file

@ -0,0 +1 @@
/usr/bin/hassio false root 0755 0755

View file

@ -0,0 +1,9 @@
#!/usr/bin/execlineb -S0
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Take down the S6 supervision tree when the ttyd daemon fails
# ==============================================================================
if -n { s6-test $# -ne 0 }
if -n { s6-test ${1} -eq 256 }
s6-svscanctl -t /var/run/s6/services

View file

@ -0,0 +1,42 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: Terminal
# Runs the ttyd daemon
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
readonly TTYD_COMMAND=(tmux new -A -s ttyd zsh)
declare -a ttyd_options
hass.log.info 'Starting the ttyd daemon'
# Set daemon debug level
if hass.debug; then
ttyd_options+=(-d10)
else
ttyd_options+=(-d2)
fi
# Add default options
ttyd_options+=(--reconnect 30)
ttyd_options+=(--port 7681)
# Add SSL, when enabled.
if hass.config.true 'ssl'; then
ttyd_options+=(--ssl)
ttyd_options+=(--ssl-cert "/ssl/$(hass.config.get 'certfile')")
ttyd_options+=(--ssl-key "/ss/$(hass.config.get 'keyfile')")
fi
# Add login credentials, when enabled.
if hass.config.has_value 'username' && hass.config.has_value 'password'; then
ttyd_options+=(--credential)
ttyd_options+=("$(hass.config.get 'username'):$(hass.config.get 'password')")
fi
# Change working directory
cd /root || hass.die 'Unable to change working directory'
# Run the ttyd daemon
ttyd "${ttyd_options[@]}" "${TTYD_COMMAND[@]}"

View file

@ -9,6 +9,8 @@ if [ "$1" == "help" ] || [ "$#" -lt 2 ]; then
HomeAssistant:
$ hassio homeassistant logs
$ hassio homeassistant restart
$ hassio homeassistant stop
$ hassio homeassistant start
$ hassio homeassistant update
$ hassio homeassistant check
@ -67,7 +69,7 @@ function call_api() {
######
# homeassistant functions
if [ "$1" == "homeassistant" ]; then
hass_cmd=('logs' 'restart' 'update' 'check')
hass_cmd=('logs' 'restart' 'update' 'check' 'start' 'stop')
if [[ ! ${hass_cmd[*]} =~ $2 ]]; then
echo "No homeassistant command '$2' found!"
exit 1