mirror of
https://github.com/hassio-addons/repository.git
synced 2025-05-06 20:21:26 +00:00
Merge pull request #13 from hassio-addons/repository-restructure
Repository restructure
This commit is contained in:
commit
59e4a1c3ca
35 changed files with 65 additions and 3107 deletions
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,3 +1,9 @@
|
|||
**NOTE**
|
||||
|
||||
This is the main repository. If you have problems with one of our add-ons,
|
||||
then _PLEASE DO NOT_ create an issue in this GitHub project. Instead,
|
||||
create an issue in the project that goes with the specific addon.
|
||||
|
||||
## Problem/Motivation
|
||||
|
||||
> (Why the issue was filed)
|
||||
|
|
55
README.md
55
README.md
|
@ -1,4 +1,4 @@
|
|||
# Third party Hass.io add-ons for Home Assistant
|
||||
# Community Hass.io add-ons for Home Assistant
|
||||
|
||||
![Project Stage][project-stage-shield]
|
||||
![Maintenance][maintenance-shield]
|
||||
|
@ -25,7 +25,7 @@ https://github.com/hassio-addons/repository
|
|||
|
||||
## Add-ons provided by this repository
|
||||
|
||||
### ✓ [Homebridge](homebridge)
|
||||
### ✓ [Homebridge][addon-homebridge]
|
||||
|
||||
![Latest Version][homebridge-version-shield]
|
||||
![Supports armhf Architecture][homebridge-armhf-shield]
|
||||
|
@ -37,9 +37,9 @@ https://github.com/hassio-addons/repository
|
|||
Homebridge is a server that emulates the iOS HomeKit API, allowing you to
|
||||
control your Home Assistant through via Apple devices (including Siri).
|
||||
|
||||
[:books: Homebridge add-on documentation](homebridge)
|
||||
[:books: Homebridge add-on documentation][addon-homebridge]
|
||||
|
||||
### ✓ [SSH - Secure Shell](ssh)
|
||||
### ✓ [SSH - Secure Shell][addon-ssh]
|
||||
|
||||
![Latest Version][ssh-version-shield]
|
||||
![Supports armhf Architecture][ssh-armhf-shield]
|
||||
|
@ -50,11 +50,11 @@ control your Home Assistant through via Apple devices (including Siri).
|
|||
|
||||
Log in to your Hass.io Home Assistant instance using SSH.
|
||||
This is an enhanced version of the provided SSH add-on by Home Assistant and
|
||||
focusses on security, usability and flexibility.
|
||||
focusses on security, usability, and flexibility.
|
||||
|
||||
[:books: SSH add-on documentation](ssh)
|
||||
[:books: SSH add-on documentation][addon-ssh]
|
||||
|
||||
### ✓ [Terminal](terminal)
|
||||
### ✓ [Terminal][addon-terminal]
|
||||
|
||||
![Latest Version][terminal-version-shield]
|
||||
![Supports armhf Architecture][terminal-armhf-shield]
|
||||
|
@ -64,15 +64,36 @@ focusses on security, usability and flexibility.
|
|||
![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.
|
||||
a web terminal. It is like SSH but in your Home Assistant frontend.
|
||||
|
||||
[:books: Terminal add-on documentation](terminal)
|
||||
[:books: Terminal add-on documentation][addon-terminal]
|
||||
|
||||
## Changelog
|
||||
|
||||
This add-on repository itself does not keep a change log, the individual
|
||||
add-ons, however, do. The format is based on [Keep a Changelog][keepchangelog]
|
||||
and these add-ons adheres to [Semantic Versioning][semver].
|
||||
moreover, these add-ons adhere to [Semantic Versioning][semver].
|
||||
|
||||
## Support
|
||||
|
||||
Got questions?
|
||||
|
||||
You have several options to get them answered:
|
||||
|
||||
- The Home Assistant [Community Forums][forums], we have a
|
||||
[dedicated topic][forums] 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]
|
||||
|
||||
You could also open an issue here on GitHub. Note, we use a separate
|
||||
GitHub repository for each add-on. Please ensure you are creating the issue
|
||||
on the correct GitHub repository matching the add-on.
|
||||
|
||||
- [Open an issue for the addon: Homebridge][homebridge-issue]
|
||||
- [Open an issue for the addon: SSH - Secure Shell][ssh-issue]
|
||||
- [Open an issue for the addon: Terminal][terminal-issue]
|
||||
- For a general repository issues or add-on ideas [open a issue here][issue]
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -84,7 +105,7 @@ We've set up a separate document for our [contribution guidelines](CONTRIBUTING.
|
|||
Thank you for being involved! :heart_eyes:
|
||||
|
||||
We are also looking for maintainers!
|
||||
Please send [Franck Nijhof][frenck] an message when you are interested in becoming one.
|
||||
Please send [Franck Nijhof][frenck] a message when you are interested in becoming one.
|
||||
|
||||
## Authors & contributors
|
||||
|
||||
|
@ -117,30 +138,40 @@ 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.
|
||||
|
||||
[issue]: https://github.com/hassio-addons/repository/issues
|
||||
[addon-homebridge]: https://github.com/hassio-addons/addon-homebridge
|
||||
[addon-ssh]: https://github.com/hassio-addons/addon-ssh
|
||||
[addon-terminal]: https://github.com/hassio-addons/addon-terminal
|
||||
[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg
|
||||
[contributors]: https://github.com/hassio-addons/repository/graphs/contributors
|
||||
[frenck]: https://github.com/frenck
|
||||
[discord]: https://discord.gg/c5DvZ4e
|
||||
[forums]: https://community.home-assistant.io/t/repository-community-hass-io-add-ons/24705?u=frenck
|
||||
[frenck]: https://community.home-assistant.io/u/frenck/summary
|
||||
[homebridge-aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
|
||||
[homebridge-amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
|
||||
[homebridge-armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
|
||||
[homebridge-i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
|
||||
[homebridge-issue]: https://github.com/hassio-addons/addon-homebridge/issues
|
||||
[homebridge-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/homebridge-armhf.svg
|
||||
[homebridge-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/homebridge-armhf.svg
|
||||
[keepchangelog]: http://keepachangelog.com/en/1.0.0/
|
||||
[license-shield]: https://img.shields.io/github/license/hassio-addons/repository.svg
|
||||
[maintenance-shield]: https://img.shields.io/maintenance/yes/2017.svg
|
||||
[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
|
||||
[reddit]: https://reddit.com/r/homeassistant
|
||||
[semver]: http://semver.org/spec/v2.0.0.html
|
||||
[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-issue]: https://github.com/hassio-addons/addon-ssh/issues
|
||||
[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-issue]: https://github.com/hassio-addons/addon-terminal/issues
|
||||
[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/
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
for arch in "armhf" "aarch64" "i386" "amd64"
|
||||
do
|
||||
./bin/create_hassio_addon.sh -a $arch "$@" &
|
||||
done
|
||||
wait
|
|
@ -1,173 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
BUILD_CONTAINER_NAME=hassio-addons-$$
|
||||
DOCKER_PUSH="true"
|
||||
DOCKER_CACHE="true"
|
||||
DOCKER_WITH_LATEST="true"
|
||||
BRANCH=master
|
||||
REPOSITORY=https://github.com/hassio-addons/repository
|
||||
|
||||
cleanup() {
|
||||
echo "[INFO] Cleanup."
|
||||
|
||||
# Stop docker container
|
||||
echo "[INFO] Cleaning up hassio-build container."
|
||||
docker stop $BUILD_CONTAINER_NAME 2> /dev/null || true
|
||||
docker rm --volumes $BUILD_CONTAINER_NAME 2> /dev/null || true
|
||||
|
||||
if [ "$1" == "fail" ]; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
trap 'cleanup fail' SIGINT SIGTERM
|
||||
|
||||
help () {
|
||||
cat << EOF
|
||||
Script for hassio addon docker build
|
||||
create_hassio_addon [options]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Display this help and exit.
|
||||
|
||||
-r, --repository https://.../addons
|
||||
Set git repository to load addon from.
|
||||
-b, --branch branch_name
|
||||
Set git branch to load addon from.
|
||||
-l, --local /path/to/repository
|
||||
Load addon from a local folder
|
||||
-s, --slug addon_slug
|
||||
Name of folder/slug
|
||||
|
||||
-a, --arch armhf|aarch64|i386|amd64
|
||||
Arch for addon build.
|
||||
-t, --test
|
||||
Don't upload the build to docker hub.
|
||||
-n, --no-cache
|
||||
Disable build from cache
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key=$1
|
||||
case $key in
|
||||
-h|--help)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
-r|--repository)
|
||||
REPOSITORY=$2
|
||||
shift
|
||||
;;
|
||||
-b|--branch)
|
||||
BRANCH=$2
|
||||
shift
|
||||
;;
|
||||
-l|--local)
|
||||
LOCAL_REPOSITORY=$2
|
||||
shift
|
||||
;;
|
||||
-s|--slug)
|
||||
SLUG=$2
|
||||
shift
|
||||
;;
|
||||
-a|--arch)
|
||||
ARCH=$2
|
||||
shift
|
||||
;;
|
||||
-t|--test)
|
||||
DOCKER_PUSH="false"
|
||||
;;
|
||||
-n|--no-cache)
|
||||
DOCKER_CACHE="false"
|
||||
;;
|
||||
*)
|
||||
echo "[WARNING] $0 : Argument '$1' unknown. Ignoring."
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Sanity checks
|
||||
if [ "$ARCH" != 'armhf' ] && [ "$ARCH" != 'aarch64' ] && [ "$ARCH" != 'i386' ] && [ "$ARCH" != 'amd64' ]; then
|
||||
echo "Error: $ARCH is not a supported platform for hassio-supervisor!"
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$SLUG" ]; then
|
||||
echo "[ERROR] please set a slug!"
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the absolute script location
|
||||
pushd "$(dirname "$0")" > /dev/null 2>&1
|
||||
SCRIPTPATH=$(pwd)
|
||||
popd > /dev/null 2>&1
|
||||
|
||||
BASE_IMAGE="homeassistant\/$ARCH-base:latest"
|
||||
BUILD_DIR=${BUILD_DIR:=$SCRIPTPATH}
|
||||
WORKSPACE=${BUILD_DIR:=$SCRIPTPATH}/hassio-supervisor-$ARCH
|
||||
ADDON_WORKSPACE=$WORKSPACE/$SLUG
|
||||
|
||||
# setup docker
|
||||
echo "[INFO] cleanup old WORKSPACE"
|
||||
rm -rf "$ADDON_WORKSPACE"
|
||||
|
||||
echo "[INFO] Setup docker for addon"
|
||||
mkdir -p "$BUILD_DIR"
|
||||
mkdir -p "$WORKSPACE"
|
||||
|
||||
|
||||
if [ -z "$LOCAL_REPOSITORY" ]; then
|
||||
git clone "$REPOSITORY" "$WORKSPACE"
|
||||
cd "$WORKSPACE"; git checkout "$BRANCH"
|
||||
|
||||
if [ ! -d "$ADDON_WORKSPACE" ]; then
|
||||
echo "Error: $ADDON not found inside Repo!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
cp -r "$LOCAL_REPOSITORY/$SLUG" "$ADDON_WORKSPACE"
|
||||
fi
|
||||
|
||||
# Init docker
|
||||
echo "[INFO] Setup dockerfile"
|
||||
|
||||
sed -i "s/{arch}/${ARCH}/g" "$ADDON_WORKSPACE/config.json"
|
||||
DOCKER_TAG=$(jq --raw-output ".version" "$ADDON_WORKSPACE/config.json")
|
||||
|
||||
# If set custom image in file
|
||||
DOCKER_IMAGE=$(jq --raw-output ".image // empty" "$ADDON_WORKSPACE/config.json")
|
||||
|
||||
# Replace hass.io vars
|
||||
sed -i "s/%%BASE_IMAGE%%/${BASE_IMAGE}/g" "$ADDON_WORKSPACE/Dockerfile"
|
||||
sed -i "s/#${ARCH}:FROM/FROM/g" "$ADDON_WORKSPACE/Dockerfile"
|
||||
sed -i "s/%%ARCH%%/${ARCH}/g" "$ADDON_WORKSPACE/Dockerfile"
|
||||
echo "LABEL io.hass.version=\"$DOCKER_TAG\" io.hass.arch=\"$ARCH\" io.hass.type=\"addon\"" >> "$ADDON_WORKSPACE/Dockerfile"
|
||||
|
||||
# Run build
|
||||
echo "[INFO] start docker build"
|
||||
docker stop $BUILD_CONTAINER_NAME 2> /dev/null || true
|
||||
docker rm --volumes $BUILD_CONTAINER_NAME 2> /dev/null || true
|
||||
docker run --rm \
|
||||
-v "$ADDON_WORKSPACE":/docker \
|
||||
-v ~/.docker:/root/.docker \
|
||||
-e DOCKER_PUSH=$DOCKER_PUSH \
|
||||
-e DOCKER_CACHE=$DOCKER_CACHE \
|
||||
-e DOCKER_WITH_LATEST=$DOCKER_WITH_LATEST \
|
||||
-e DOCKER_IMAGE="$DOCKER_IMAGE" \
|
||||
-e DOCKER_TAG="$DOCKER_TAG" \
|
||||
--name $BUILD_CONTAINER_NAME \
|
||||
--privileged \
|
||||
homeassistant/docker-build-env \
|
||||
/run-docker.sh
|
||||
|
||||
echo "[INFO] cleanup WORKSPACE"
|
||||
cd "$BUILD_DIR"
|
||||
rm -rf "$WORKSPACE"
|
||||
|
||||
cleanup "okay"
|
||||
exit 0
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
for addon in "$@";
|
||||
do
|
||||
if [ -z $TRAVIS_COMMIT_RANGE ] || \
|
||||
git diff --name-only $TRAVIS_COMMIT_RANGE | grep -q $addon;
|
||||
then
|
||||
archs=$(jq -r '.arch // ["armhf","amd64","aarch64","i386"] | .[]' ${addon}/config.json)
|
||||
for arch in $archs
|
||||
do
|
||||
./bin/create_hassio_addon.sh -a $arch -s $addon -l .
|
||||
done
|
||||
else
|
||||
echo "No change in commit range $TRAVIS_COMMIT_RANGE, skipping build."
|
||||
fi
|
||||
done
|
|
@ -1,18 +0,0 @@
|
|||
# Hass.io Add-on Changelog: Homebridge
|
||||
|
||||
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.1 - 2017-08-15
|
||||
### Fixes
|
||||
- Homebridge pin generated with additional dash [#3](https://github.com/hassio-addons/repository/issues/3)
|
||||
|
||||
## 1.0.0 - 2017-08-14
|
||||
### Added
|
||||
- First version of the Homebridge Add-on
|
||||
- This CHANGELOG file
|
|
@ -1,29 +0,0 @@
|
|||
FROM %%BASE_IMAGE%%
|
||||
MAINTAINER Franck Nijhof <frenck@geekchimp.com>
|
||||
|
||||
# Add env
|
||||
ENV LANG="C.UTF-8"
|
||||
|
||||
# Copy run file
|
||||
COPY files/run.sh /
|
||||
|
||||
# Setup base
|
||||
RUN apk add --no-cache jq git python make g++ libffi-dev openssl-dev openrc dbus \
|
||||
avahi-compat-libdns_sd avahi-dev avahi-tools avahi-ui-tools \
|
||||
nodejs-current nodejs-current-npm yarn && \
|
||||
mkdir -p /var/run/dbus && \
|
||||
mkdir -p /var/run/avahi-daemon && \
|
||||
chown messagebus:messagebus /var/run/dbus && \
|
||||
chown avahi:avahi /var/run/avahi-daemon && \
|
||||
yarn global add node-gyp && \
|
||||
yarn global add homebridge@0.4.22 && \
|
||||
yarn global add homebridge-homeassistant && \
|
||||
npm cache clean && \
|
||||
yarn cache clean && \
|
||||
chmod a+x /run.sh
|
||||
|
||||
# Copy configuration files
|
||||
COPY files/avahi-daemon.conf /etc/avahi/
|
||||
COPY files/homebridge-config.json /root/
|
||||
|
||||
CMD [ "/run.sh" ]
|
|
@ -1,288 +1,7 @@
|
|||
# Hass.io Add-on: Homebridge
|
||||
# Community Hass.io Add-on: Homebridge
|
||||
|
||||
![Project Stage][project-stage-shield]
|
||||
![Maintenance][maintenance-shield]
|
||||
![Awesome][awesome-shield]
|
||||
[![License][license-shield]](LICENSE.md)
|
||||
This is just a configuration stub to make the Hass.io repository work.
|
||||
|
||||
The add-on itself can be found at the following URL:
|
||||
|
||||
This add-on provides the installation, configuration, and integration for
|
||||
[Homebridge][homebridge].
|
||||
|
||||
Homebridge is a server that emulates the iOS HomeKit API, allowing you to
|
||||
control your Home Assistant through via Apple devices (including Siri).
|
||||
|
||||
Since Siri supports devices added through HomeKit, this means that with
|
||||
Homebridge you can ask Siri to control devices that don't have any support for
|
||||
HomeKit at all. For instance, using just some of the available plugins,
|
||||
you can say:
|
||||
|
||||
* _Siri, unlock the back door._
|
||||
* _Siri, open the garage door._
|
||||
* _Siri, turn on the coffee maker._
|
||||
* _Siri, turn on the living room lights._
|
||||
* _Siri, good morning!_
|
||||
|
||||
## 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]
|
||||
|
||||
## 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 "Homebridge" add-on
|
||||
3. Start the "Homebridge" add-on
|
||||
4. Check the logs of the "Homebridge" add-on to see if everything went well and
|
||||
to find the pin code needed to add your Home Assistant instance to
|
||||
your iOS device
|
||||
|
||||
Please read the rest of this document further instructions.
|
||||
|
||||
## Configuration
|
||||
|
||||
On the first run, this add-on will create the necessary configuration files
|
||||
for you. Stored in `/config/homebridge/`. You can modify the configuration
|
||||
to your own liking. For documentation on configuring Homebridge, please refer
|
||||
to the [Homebridge GitHub][homebridge] repository. For documentation on
|
||||
configuring the Home Assistant for Homebridge plugin, please refer to the
|
||||
[Home Assistant for Homebridge GitHub][homebridge-homeassistant] repository.
|
||||
|
||||
The add-on has a limited configuration possibility as well.
|
||||
|
||||
_Please remember to restart the add-on when the configuration changes._
|
||||
|
||||
Example add-on configuration:
|
||||
```json
|
||||
{
|
||||
"debug": false,
|
||||
"plugins": []
|
||||
}
|
||||
```
|
||||
|
||||
**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 all the services in debug mode, which causes
|
||||
more output in the log files.
|
||||
|
||||
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: `plugins`**
|
||||
|
||||
This Homebridge add-on has support for installing additional Homebridge plugins.
|
||||
Plugins are NodeJS modules published through NPM and tagged with the keyword
|
||||
`homebridge-plugin`. They must have a name with the prefix `homebridge-`,
|
||||
like `homebridge-mysmartlock`.
|
||||
|
||||
The `homebridge-homeassistant` plugin is already installed for you.
|
||||
|
||||
You can install a plugin by adding it to the add-on configuration. The add-on
|
||||
will ensure the plugin is installed on start.
|
||||
|
||||
Example add-on configuration:
|
||||
```json
|
||||
{
|
||||
"debug": false,
|
||||
"plugins": [
|
||||
"homebridge-dummy",
|
||||
"homebridge-mysmartlock"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can explore all available plugins at the NPM website by [searching for the
|
||||
keyword `homebridge-plugin`][homebridge-plugins].
|
||||
|
||||
## Adding Homebridge to iOS
|
||||
|
||||
Using the Home app (or most other HomeKit apps), you should be able to add the
|
||||
single accessory "Home Assistant", assuming that you're still running the
|
||||
Homebridge add-on and you're on the same (Wifi) network. Adding this accessory
|
||||
will automatically add all accessories and platforms defined in your
|
||||
Home Assistant instance.
|
||||
|
||||
When you attempt to add the "Home Assistant" accessory, it will ask for a
|
||||
"PIN code". This pin code is randomly generated when this add-on is run for
|
||||
the first time. You can find the generated PIN code in the add-on logs and in
|
||||
your `/config/homebridge/config.json` file (where you, of course,
|
||||
can change it as well).
|
||||
|
||||
|
||||
## Known issues and limitations
|
||||
|
||||
* Once your device has been added to HomeKit, you should be able to tell Siri to
|
||||
control your devices. However, realize that Siri is a cloud service, and iOS may
|
||||
need some time to synchronize your device information with iCloud.
|
||||
* Siri will almost always prefer its default phrase handling over HomeKit
|
||||
devices. For instance, if you name your Sonos device "Radio" and try saying
|
||||
"Siri, turn on the Radio" then Siri will probably start playing an iTunes Radio
|
||||
station on your phone. Even if you name it "Sonos" and say
|
||||
"Siri, turn on the Sonos", Siri will probably just launch the Sonos app instead.
|
||||
This is why, for instance, the suggested `name` for the Sonos accessory
|
||||
is "Speakers".
|
||||
* One installation of Homebridge can only expose 100 accessories due to a
|
||||
HomeKit limit.
|
||||
* Once an accessory has been added to the Home app, changing its name via
|
||||
Homebridge won't be automatically reflected in iOS. You must change it via
|
||||
the Home app as well.
|
||||
* IPv6 support has been removed from this addon, because of known issues with
|
||||
libraries used by Homebridge. If you rely solely on IPv6 in your network,
|
||||
this add-on would not work.
|
||||
* If you have set up SSL using a self-signed certificate, you will need to
|
||||
set verify_ssl to false in your `/config/homebridge/config.json` file to allow
|
||||
bypassing the Node.js certificate checks.
|
||||
* Errors on startup. The following errors are experienced when starting
|
||||
Homebridge and can be safely ignored.
|
||||
```
|
||||
*** WARNING *** The program 'nodejs' uses the Apple Bonjour compatibility layer of Avahi
|
||||
*** WARNING *** Please fix your application to use the native API of Avahi!
|
||||
*** WARNING *** For more information see http://0pointerde/avahi-compat?s=libdns_sd&e=nodejs
|
||||
*** WARNING *** The program 'nodejs' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi
|
||||
*** WARNING *** Please fix your application to use the native API of Avahi!
|
||||
*** WARNING *** For more information see http://0pointerde/avahi-compat?s=libdns_sd&e=nodejs&f=DNSServiceRegister
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
**Homebridge cannot connect or login to Home Assistant**
|
||||
|
||||
Please be sure to set the `host` and `password` parameters in the
|
||||
`/config/homebridge/config.json` file.
|
||||
Normally `http://172.17.0.1:8123` should be a sufficient `host` to use when
|
||||
running hass.io.
|
||||
If a password protects your Home Assistant instance, you'll also need to
|
||||
set the `password`, which is empty by default.
|
||||
|
||||
**My iOS App Can't Find Homebridge/Home Assistant**
|
||||
|
||||
Two reasons why Homebridge may not be discoverable:
|
||||
|
||||
1. Homebridge server thinks it's been paired with, but iOS thinks otherwise.
|
||||
Fix: deleted `persist/` directory which is in your `config/homebridge` directory
|
||||
and restart the add-on.
|
||||
|
||||
2. iOS device has gotten your Homebridge `username` (looks like a MAC address)
|
||||
"stuck" somehow, where it's in the database but inactive. Fix: change your
|
||||
`username` in the "bridge" section of `/config/homebridge/config.json` to be
|
||||
some new value and restart the add-on.
|
||||
|
||||
|
||||
## 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
|
||||
- [Nick Farina][nfarina] for developing [Homebrige][homebridge]
|
||||
|
||||
This add-on has been inspired by the following repositories:
|
||||
- [docker-homebridge][oznu-docker-homebridge] by [Oznu][oznu]
|
||||
- [homebridge-docker][ckuburlis-homebridge-docker]by [ckuburlis]
|
||||
- [hassio-addons][olivierguerriat-hassio-addons] by [Olivier Guerriat][olivierguerriat]
|
||||
|
||||
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/homebridge-aarch64
|
||||
[aarch64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/homebridge-aarch64.svg
|
||||
[aarch64-microbadger]: https://microbadger.com/images/hassioaddons/homebridge-aarch64
|
||||
[aarch64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/homebridge-aarch64.svg
|
||||
[aarch64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/homebridge-aarch64.svg
|
||||
[amd64-arch-shield]: https://img.shields.io/badge/architecture-amd64-blue.svg
|
||||
[amd64-dockerhub]: https://hub.docker.com/r/hassioaddons/homebridge-amd64
|
||||
[amd64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/homebridge-amd64.svg
|
||||
[amd64-microbadger]: https://microbadger.com/images/hassioaddons/homebridge-amd64
|
||||
[amd64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/homebridge-amd64.svg
|
||||
[amd64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/homebridge-amd64.svg
|
||||
[armhf-arch-shield]: https://img.shields.io/badge/architecture-armhf-blue.svg
|
||||
[armhf-dockerhub]: https://hub.docker.com/r/hassioaddons/homebridge-armhf
|
||||
[armhf-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/homebridge-armhf.svg
|
||||
[armhf-microbadger]: https://microbadger.com/images/hassioaddons/homebridge-armhf
|
||||
[armhf-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/homebridge-armhf.svg
|
||||
[armhf-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/homebridge-armhf.svg
|
||||
[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg
|
||||
[ckuburlis-homebridge-docker]: https://github.com/ckuburlis/homebridge-docker
|
||||
[ckuburlis]: https://github.com/ckuburlis
|
||||
[home-assistant]: https://home-assistant.io
|
||||
[homebridge-homeassistant]: https://github.com/home-assistant/homebridge-homeassistant
|
||||
[homebridge-plugins]: https://www.npmjs.com/search?q=homebridge-plugin
|
||||
[homebridge]: https://github.com/nfarina/homebridge
|
||||
[i386-arch-shield]: https://img.shields.io/badge/architecture-i386-blue.svg
|
||||
[i386-dockerhub]: https://hub.docker.com/r/hassioaddons/homebridge-i386
|
||||
[i386-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/homebridge-i386.svg
|
||||
[i386-microbadger]: https://microbadger.com/images/hassioaddons/homebridge-i386
|
||||
[i386-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/homebridge-i386.svg
|
||||
[i386-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/homebridge-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
|
||||
[nfarina]: https://github.com/nfarina
|
||||
[olivierguerriat-hassio-addons]: https://github.com/olivierguerriat/hassio-addons
|
||||
[olivierguerriat]: https://github.com/olivierguerriat
|
||||
[oznu-docker-homebridge]: https://github.com/oznu/docker-homebridge
|
||||
[oznu]: https://github.com/oznu
|
||||
[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
|
||||
[repository]: https://github.com/hassio-addons/repository
|
||||
https://github.com/hassio-addons/addon-homebridge
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.1",
|
||||
"slug": "homebridge",
|
||||
"description": "HomeKit support for your Home Assistant instance using Homebridge",
|
||||
"url": "https://github.com/hassio-addons/repository/tree/master/homebridge",
|
||||
"url": "https://github.com/hassio-addons/addon-homebridge",
|
||||
"startup": "application",
|
||||
"boot": "auto",
|
||||
"host_network": true,
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
[server]
|
||||
host-name=hassio
|
||||
domain-name=local
|
||||
#browse-domains=0pointer.de, zeroconf.org
|
||||
use-ipv4=yes
|
||||
use-ipv6=no
|
||||
#allow-interfaces=eth0
|
||||
#deny-interfaces=eth1
|
||||
#check-response-ttl=no
|
||||
#use-iff-running=no
|
||||
enable-dbus=yes
|
||||
#disallow-other-stacks=no
|
||||
#allow-point-to-point=no
|
||||
#cache-entries-max=4096
|
||||
#clients-max=4096
|
||||
#objects-per-client-max=1024
|
||||
#entries-per-entry-group-max=32
|
||||
ratelimit-interval-usec=1000000
|
||||
ratelimit-burst=1000
|
||||
|
||||
[wide-area]
|
||||
enable-wide-area=yes
|
||||
|
||||
[publish]
|
||||
#disable-publishing=no
|
||||
#disable-user-service-publishing=no
|
||||
#add-service-cookie=no
|
||||
#publish-addresses=yes
|
||||
publish-hinfo=no
|
||||
publish-workstation=no
|
||||
#publish-domain=yes
|
||||
#publish-dns-servers=192.168.50.1, 192.168.50.2
|
||||
#publish-resolv-conf-dns-servers=yes
|
||||
#publish-aaaa-on-ipv4=yes
|
||||
#publish-a-on-ipv6=no
|
||||
|
||||
[reflector]
|
||||
#enable-reflector=no
|
||||
#reflect-ipv=no
|
||||
|
||||
[rlimits]
|
||||
#rlimit-as=
|
||||
rlimit-core=0
|
||||
rlimit-data=4194304
|
||||
rlimit-fsize=0
|
||||
rlimit-nofile=768
|
||||
rlimit-stack=4194304
|
||||
#rlimit-nproc=3
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"bridge": {
|
||||
"name": "Home Assistant",
|
||||
"username": "%%USERNAME%%",
|
||||
"port": 51826,
|
||||
"pin": "%%PIN%%"
|
||||
},
|
||||
"description": "Homebridge for Home Assistant",
|
||||
"accessories": [],
|
||||
"platforms": [
|
||||
{
|
||||
"platform": "HomeAssistant",
|
||||
"name": "HomeAssistant",
|
||||
"host": "http://172.17.0.1:8123",
|
||||
"password": "",
|
||||
"supported_types": [
|
||||
"binary_sensor",
|
||||
"climate",
|
||||
"cover",
|
||||
"device_tracker",
|
||||
"fan",
|
||||
"group",
|
||||
"input_boolean",
|
||||
"light",
|
||||
"lock",
|
||||
"media_player",
|
||||
"scene",
|
||||
"sensor",
|
||||
"switch"
|
||||
],
|
||||
"logging": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,434 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# Hass.io Add-on for Home Assistant: Homebridge
|
||||
# ==============================================================================
|
||||
|
||||
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_DBUS_ID_FAILED=3 # Failed to generated a unique D-Bus ID
|
||||
readonly EX_PLUGIN_FAILED=4 # Homebridge plugin installation failed
|
||||
readonly EX_DBUS_DAEMON=5 # Failed to start D-Bus daemon
|
||||
readonly EX_PID_AVAHI=6 # Failed to remove Avahi daemon PID file
|
||||
readonly EX_PID_DBUS=7 # Failed to remove D-Bus daemon PID file
|
||||
readonly EX_PATCH_ERROR=8 # Failed to apply patch
|
||||
readonly EX_HOMEBRIDGE_DIR=9 # Failed to create Homebridge config directory
|
||||
readonly EX_HOMEBRIDGE_FILE=10 # Failed to create Homebridge config file
|
||||
readonly EX_HOMEBRIDGE_USER=11 # Failed to set Homebridge user config
|
||||
readonly EX_HOMEBRIDGE_PIN=12 # Failed to set Homebridge user pin
|
||||
|
||||
# Configuration paths
|
||||
readonly CONFIG_PATH=/data/options.json
|
||||
readonly HOMEBRIDGE_CONFIG_FILE=/config/homebridge/config.json
|
||||
readonly HOMEBRIDGE_TEMPLATE_CONFIG_FILE=/root/homebridge-config.json
|
||||
|
||||
# PID Files
|
||||
readonly PID_FILE_DBUS=/var/run/dbus.pid
|
||||
readonly PID_FILE_AVAHI=/var/run/avahi-daemon/pid
|
||||
|
||||
# D-Bus System bus socket file location
|
||||
readonly DBUS_SYSTEM_SOCKET=/var/run/dbus/system_bus_socket
|
||||
|
||||
# Debug mode?
|
||||
readonly DEBUG=$(jq --raw-output ".debug" $CONFIG_PATH)
|
||||
|
||||
# ==============================================================================
|
||||
# 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
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Finds the MAC address of the main interface
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# MAC address of the main interface (upper-cased)
|
||||
# ------------------------------------------------------------------------------
|
||||
get_mac_addr() {
|
||||
local interface
|
||||
local mac
|
||||
|
||||
interface=$(ip route show default | awk '/default/ {print $5}')
|
||||
mac=$(cat "/sys/class/net/$interface/address")
|
||||
|
||||
echo "${mac^^}"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generates a random pin number for HomeKit (###-##-### format)
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# The generated random pin number
|
||||
# ------------------------------------------------------------------------------
|
||||
generate_homekit_pin() {
|
||||
local pin
|
||||
|
||||
pin=$(< /dev/urandom tr -dc 0-9 | head -c3)
|
||||
pin+="-"
|
||||
pin+=$(< /dev/urandom tr -dc 0-9 | head -c2)
|
||||
pin+="-"
|
||||
pin+=$(< /dev/urandom tr -dc 0-9 | head -c3)
|
||||
|
||||
echo "$pin"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SCRIPT LOGIC
|
||||
# ==============================================================================
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Applies temporary but necessary patch to HAP NodeJS
|
||||
# Globals:
|
||||
# EX_PATCH_ERROR
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
apply_hap_nodejs_ipv6_hotfix() {
|
||||
local eventedhttp_file='/usr/local/share/.config/yarn/global/node_modules/hap-nodejs/lib/util/eventedhttp.js'
|
||||
|
||||
display_status_message 'Applying HAP NodeJS IPV6 HOTFIX'
|
||||
command patch $eventedhttp_file <<PATCH
|
||||
--- eventedhttp.js
|
||||
+++ eventedhttp.js
|
||||
@@ -57,7 +57,7 @@
|
||||
inherits(EventedHTTPServer, EventEmitter);
|
||||
|
||||
EventedHTTPServer.prototype.listen = function(targetPort) {
|
||||
- this._tcpServer.listen(targetPort);
|
||||
+ this._tcpServer.listen(targetPort, '0.0.0.0');
|
||||
|
||||
this._tcpServer.on('listening', function() {
|
||||
var port = this._tcpServer.address().port;
|
||||
PATCH
|
||||
|
||||
# shellcheck disable=SC2181
|
||||
if [[ "$?" -ne 0 ]];
|
||||
then
|
||||
display_error_message 'Patching HAP NodeJS failed' "$EX_PATCH_ERROR"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Ensures D-Bus UUID exists and has the uuid in it
|
||||
# Globals:
|
||||
# EX_DBUS_ID_FAILED
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_dbus_id() {
|
||||
display_status_message 'Ensuring D-Bus unique ID exists'
|
||||
|
||||
command dbus-uuidgen --ensure || display_error_message \
|
||||
'Failed to generated unique D-Bus ID' "$EX_DBUS_ID_FAILED"
|
||||
|
||||
# Somehow we need this sleep. Atm it is unclear why...
|
||||
sleep 2
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Install list of user requested Homebridge Plugins
|
||||
# Globals:
|
||||
# EX_PLUGIN_FAILED
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
install_plugins() {
|
||||
local plugins
|
||||
|
||||
plugins=$(get_config "plugins" true)
|
||||
for plugin in $plugins;
|
||||
do
|
||||
display_status_message "Installing Homebridge plugin $plugin"
|
||||
|
||||
command yarn global add "$plugin" || display_error_message \
|
||||
"Failed installing Homebridge plugin $plugin" $EX_PLUGIN_FAILED
|
||||
done
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Removes old PID files that may be left behind from last run
|
||||
# Globals:
|
||||
# EX_PID_AVAHI
|
||||
# EX_PID_DBUS
|
||||
# PID_FILE_AVAHI
|
||||
# PID_FILE_DBUS
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
remove_old_pid_files() {
|
||||
display_status_message 'Ensuring old PID files are absent'
|
||||
|
||||
if [[ -e "$PID_FILE_AVAHI" ]];
|
||||
then
|
||||
display_status_message 'Removing old Avahi daemon PID file'
|
||||
command rm -f "$PID_FILE_AVAHI" || display_error_message \
|
||||
'Failed to removed Avahi daemon PID file' "$EX_PID_AVAHI"
|
||||
fi
|
||||
|
||||
if [[ -e "$PID_FILE_DBUS" ]];
|
||||
then
|
||||
display_status_message 'Removing old D-Bus daemon PID file'
|
||||
command rm -f "$PID_FILE_DBUS" || display_error_message \
|
||||
'Failed to remove D-Bus daemon PID file' "$EX_PID_DBUS"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Start the Avahi daemon in the background
|
||||
# Globals:
|
||||
# DEBUG
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
start_avahi_daemon() {
|
||||
display_status_message 'Starting Avahi daemon'
|
||||
|
||||
if [[ "$DEBUG" == "true" ]];
|
||||
then
|
||||
command avahi-daemon --debug &
|
||||
else
|
||||
command avahi-daemon &
|
||||
fi
|
||||
|
||||
# Waiting 5 seconds to allow Avahi to register itself
|
||||
sleep 5
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Applies temporary but necessary patch to HAP NodeJS
|
||||
# Globals:
|
||||
# EX_DBUS_DAEMON
|
||||
# DBUS_SYSTEM_SOCKET
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
start_dbus_daemon() {
|
||||
display_status_message 'Starting D-Bus daemon'
|
||||
|
||||
command dbus-daemon --system || display_error_message \
|
||||
'Failed to start D-Bus daemon' $EX_DBUS_DAEMON
|
||||
|
||||
display_debug_message 'Waiting until system bus socket is ready'
|
||||
|
||||
until [[ -e "$DBUS_SYSTEM_SOCKET" ]];
|
||||
do
|
||||
display_debug_message 'Still waiting...'
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Starts Homebridge
|
||||
# Globals:
|
||||
# HOMEBRIDGE_CONFIG_FILE
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
start_homebridge() {
|
||||
display_status_message 'Starting Homebridge'
|
||||
|
||||
if [[ "$DEBUG" == "true" ]];
|
||||
then
|
||||
command homebridge -D -U "$(dirname "$HOMEBRIDGE_CONFIG_FILE")"
|
||||
else
|
||||
command homebridge -U "$(dirname "$HOMEBRIDGE_CONFIG_FILE")"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Generates an initial Homebridge configuration file
|
||||
# Globals:
|
||||
# HOMEBRIDGE_CONFIG_FILE
|
||||
# EX_HOMEBRIDGE_DIR
|
||||
# EX_HOMEBRIDGE_FILE
|
||||
# EX_HOMEBRIDGE_USER
|
||||
# EX_HOMEBRIDGE_PIN
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
generate_homebridge_config() {
|
||||
local homebridge_config_dir
|
||||
|
||||
display_status_message 'Generating Homebridge configuration files'
|
||||
|
||||
homebridge_config_dir=$(dirname "$HOMEBRIDGE_CONFIG_FILE")
|
||||
if [[ ! -d "$homebridge_config_dir" ]];
|
||||
then
|
||||
display_debug_message 'Creating Homebridge configuration directory'
|
||||
command mkdir -p "$homebridge_config_dir" || display_error_message \
|
||||
'Failed to create Homebrige configuration directory' \
|
||||
"$EX_HOMEBRIDGE_DIR"
|
||||
fi
|
||||
|
||||
display_debug_message 'Copying Homebrige configuration template'
|
||||
command cp "$HOMEBRIDGE_TEMPLATE_CONFIG_FILE" "$HOMEBRIDGE_CONFIG_FILE" ||
|
||||
display_error_message 'Failed creating Homebridge configuration file' \
|
||||
"$EX_HOMEBRIDGE_FILE"
|
||||
|
||||
display_debug_message 'Setting Homebridge username based on MAC address'
|
||||
command sed -i "s/%%USERNAME%%/$(get_mac_addr)/g" \
|
||||
"$HOMEBRIDGE_CONFIG_FILE" || display_error_message \
|
||||
'Failed setting Homebridge username' "$EX_HOMEBRIDGE_USER"
|
||||
|
||||
display_debug_message 'Setting Homebridge HomeKit pin'
|
||||
command sed -i "s/%%PIN%%/$(generate_homekit_pin)/g" \
|
||||
"$HOMEBRIDGE_CONFIG_FILE" || display_error_message \
|
||||
'Failed setting Homebridge pin' "$EX_HOMEBRIDGE_PIN"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Cleanup function after execution is of the script is stopped. (trap)
|
||||
# Globals:
|
||||
# PID_FILE_AVAHI
|
||||
# PID_FILE_DBUS
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
cleanup() {
|
||||
command rm -f "$PID_FILE_AVAHI"
|
||||
command rm -f "$PID_FILE_DBUS"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# RUN LOGIC
|
||||
# ------------------------------------------------------------------------------
|
||||
# Globals:
|
||||
# EX_OK
|
||||
# HOMEBRIDGE_CONFIG_FILE
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
main() {
|
||||
trap cleanup ERR
|
||||
trap cleanup EXIT
|
||||
|
||||
install_plugins
|
||||
|
||||
remove_old_pid_files
|
||||
ensure_dbus_id
|
||||
start_dbus_daemon
|
||||
|
||||
start_avahi_daemon
|
||||
|
||||
if [[ ! -f "$HOMEBRIDGE_CONFIG_FILE" ]]; then
|
||||
generate_homebridge_config
|
||||
fi
|
||||
|
||||
apply_hap_nodejs_ipv6_hotfix
|
||||
|
||||
start_homebridge
|
||||
|
||||
exit "$EX_OK"
|
||||
}
|
||||
main
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "Third party Hass.io add-ons for Home Assistant",
|
||||
"name": "Community Hass.io add-ons for Home Assistant",
|
||||
"url": "https://github.com/hassio-addons/repository",
|
||||
"maintainer": "Franck Nijhof <frenck@geekchimp.com>"
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# Hass.io Add-on Changelog: SSH - Secure Shell
|
||||
|
||||
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.3 - 2017-08-16
|
||||
### Changed
|
||||
- Fix issue: User with key and without password was unable to log in
|
||||
This time for real ;)
|
||||
|
||||
## 1.0.2 - 2017-08-16
|
||||
### Changed
|
||||
- Fix issue: User with key and without password was unable to log in
|
||||
|
||||
## 1.0.1 - 2017-08-16
|
||||
### Changed
|
||||
- Fix issue: User with key and without password was unable to log in
|
||||
|
||||
## 1.0.0 - 2017-08-16
|
||||
### Added
|
||||
- First version of the SSH Add-on
|
||||
- This CHANGELOG file
|
|
@ -1,29 +0,0 @@
|
|||
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/sshd_config /etc/ssh/
|
||||
COPY files/motd /etc/
|
||||
COPY files/.zshrc /root/
|
||||
COPY files/.tmux.conf /root/
|
||||
COPY files/wheel /etc/sudoers.d/
|
||||
|
||||
# Setup base
|
||||
RUN apk add --no-cache jq openssh sudo zsh openssl libxml2-utils ncurses \
|
||||
curl wget net-tools bind-tools rsync git nmap wget awake \
|
||||
nano vim mosquitto-clients mariadb-client tmux && \
|
||||
git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh && \
|
||||
chmod a+x /run.sh /usr/bin/hassio && \
|
||||
sed -i -e "s/bin\/ash/bin\/zsh/" /etc/passwd && \
|
||||
touch /etc/ssh/authorized_keys && \
|
||||
chmod 0644 /etc/ssh/authorized_keys && \
|
||||
touch /var/log/btmp && \
|
||||
chmod 0600 /var/log/btmp
|
||||
|
||||
CMD [ "/run.sh" ]
|
262
ssh/README.md
262
ssh/README.md
|
@ -1,261 +1,7 @@
|
|||
# Hass.io Add-on: SSH - Secure Shell
|
||||
# Community Hass.io Add-on: SSH - Secure Shell
|
||||
|
||||
![Project Stage][project-stage-shield]
|
||||
![Maintenance][maintenance-shield]
|
||||
![Awesome][awesome-shield]
|
||||
[![License][license-shield]](LICENSE.md)
|
||||
This is just a configuration stub to make the Hass.io repository work.
|
||||
|
||||
This add-on allows you to log in to your Hass.io Home Assistant instance using
|
||||
SSH. 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.
|
||||
The add-on itself can be found at the following URL:
|
||||
|
||||
This is an enhanced version of the provided
|
||||
[SSH add-on by Home Assistant][hass-ssh] and focusses on security,
|
||||
usability and flexibility.
|
||||
|
||||
## 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
|
||||
|
||||
This add-on, of course, provides an SSH server, based on [OpenSSH][openssh].
|
||||
Additionally, it comes out of the box with the following:
|
||||
|
||||
- A secure default configuration of SSH:
|
||||
- Only allows login by the configured user, even if more users are created.
|
||||
- Only uses known secure ciphers and algorithms.
|
||||
- Limits login attempts to hold of brute-force attacks better.
|
||||
- Many more security tweaks, *this addon passes all [ssh-audit] checks
|
||||
without warnings!*
|
||||

|
||||
- Port number is configurable (You could use `1982` instead of port `22`).
|
||||
- SFTP support is disabled by default but is user configurable.
|
||||
- Username is configurable, so `root` is no longer mandatory.
|
||||
- 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. If you installed the "SSH server" add-on from the built-in add-on, then
|
||||
that one first.
|
||||
2. [Add our Hass.io add-ons repository][repository] to your Hass.io instance
|
||||
3. Install the "SSH - Secure Shell" add-on from our repository
|
||||
3. Start the "SSH - Secure Shell" add-on
|
||||
4. Check the logs of the "SSH - Secure Shell" add-on to see if everything
|
||||
went well.
|
||||
|
||||
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": true,
|
||||
"port": 22,
|
||||
"username": "hass",
|
||||
"password": "",
|
||||
"authorized_keys": [
|
||||
"ssh-rsa AASDJKJKJFWJFAFLCNALCMLAK234234....."
|
||||
],
|
||||
"sftp": false,
|
||||
"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 SSH daemon in debug mode. While SSH is
|
||||
running in daemon mode, it will be only able to accept one single connection. As
|
||||
soon as this session is ended, the addon will stop running.
|
||||
|
||||
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: `port`**
|
||||
|
||||
The default port for SSH is `22`, some security guides actually recommend to
|
||||
change the port to something else. Sometimes you'd just like to have it on
|
||||
another port. Remember, if you change to port, be sure it is not in use
|
||||
already!
|
||||
|
||||
**Option: `username`**
|
||||
|
||||
This option allows you to change to username the use when you log in via SSH.
|
||||
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.
|
||||
|
||||
_*Note*: Due to limitations, you will need to set this option to `root` in
|
||||
order to be able to enable the SFTP capabilities._
|
||||
|
||||
**Option: `password`**
|
||||
|
||||
Sets the password to log in with. Leaving it empty would disable the posibility
|
||||
to authenticate with a password. We would highly recommend not to use this
|
||||
option from a security point of view.
|
||||
|
||||
**Option: `authorized_keys`**
|
||||
|
||||
Add one or more public keys to your SSH server to use with authentication.
|
||||
This is the recommended over setting a password.
|
||||
|
||||
Please take a look at the awesome [documentation created by GitHub][github-ssh]
|
||||
about using public/private keypairs and how to create them.
|
||||
|
||||
**Option: `sftp`**
|
||||
|
||||
When set to `true` the addon will enable SFTP support on the SSH daemon.
|
||||
Please only enable it when you plan to use it.
|
||||
|
||||
_*Note*: Due to limitations, you will need to set the username to `root` in
|
||||
order to be able to enable the SFTP capabilities._
|
||||
|
||||
**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 shell 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.
|
||||
|
||||
## Known issues and limitations
|
||||
|
||||
- When SFTP is enabled, the username MUST be set to `root`.
|
||||
|
||||
## 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/ssh-aarch64
|
||||
[aarch64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/ssh-aarch64.svg
|
||||
[aarch64-microbadger]: https://microbadger.com/images/hassioaddons/ssh-aarch64
|
||||
[aarch64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/ssh-aarch64.svg
|
||||
[aarch64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/ssh-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/ssh-amd64
|
||||
[amd64-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/ssh-amd64.svg
|
||||
[amd64-microbadger]: https://microbadger.com/images/hassioaddons/ssh-amd64
|
||||
[amd64-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/ssh-amd64.svg
|
||||
[amd64-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/ssh-amd64.svg
|
||||
[armhf-arch-shield]: https://img.shields.io/badge/architecture-armhf-blue.svg
|
||||
[armhf-dockerhub]: https://hub.docker.com/r/hassioaddons/ssh-armhf
|
||||
[armhf-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/ssh-armhf.svg
|
||||
[armhf-microbadger]: https://microbadger.com/images/hassioaddons/ssh-armhf
|
||||
[armhf-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/ssh-armhf.svg
|
||||
[armhf-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/ssh-armhf.svg
|
||||
[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg
|
||||
[github-ssh]: https://help.github.com/articles/connecting-to-github-with-ssh/
|
||||
[hass-ssh]: https://home-assistant.io/addons/ssh/
|
||||
[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/ssh-i386
|
||||
[i386-layers-shield]: https://images.microbadger.com/badges/image/hassioaddons/ssh-i386.svg
|
||||
[i386-microbadger]: https://microbadger.com/images/hassioaddons/ssh-i386
|
||||
[i386-pulls-shield]: https://img.shields.io/docker/pulls/hassioaddons/ssh-i386.svg
|
||||
[i386-version-shield]: https://images.microbadger.com/badges/version/hassioaddons/ssh-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/
|
||||
[openssh]: https://www.openssh.com/
|
||||
[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg
|
||||
[repository]: https://github.com/hassio-addons/repository
|
||||
[ssh-audit]: https://github.com/arthepsy/ssh-audit
|
||||
[zsh]: https://en.wikipedia.org/wiki/Z_shell
|
||||
https://github.com/hassio-addons/addon-ssh
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.3",
|
||||
"slug": "ssh",
|
||||
"description": "Allows SSH connections to your Home Assistant instance",
|
||||
"url": "https://github.com/hassio-addons/repository/tree/master/ssh",
|
||||
"url": "https://github.com/hassio-addons/addon-ssh",
|
||||
"startup": "services",
|
||||
"boot": "auto",
|
||||
"host_network": true,
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
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
|
|
@ -1,85 +0,0 @@
|
|||
# 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"
|
101
ssh/files/hassio
101
ssh/files/hassio
|
@ -1,101 +0,0 @@
|
|||
#!/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
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
_ _ _____ ____
|
||||
| | | | |_ _/ __ \
|
||||
| |__| | __ _ ___ ___ | || | | |
|
||||
| __ |/ _` / __/ __| | || | | |
|
||||
| | | | (_| \__ \__ \_ _| || |__| |
|
||||
|_| |_|\__,_|___/___(_)_____\____/
|
||||
|
||||
|
||||
Our Cli:
|
||||
$ hassio help
|
||||
|
513
ssh/files/run.sh
513
ssh/files/run.sh
|
@ -1,513 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# Hass.io Add-on for Home Assistant: SSH
|
||||
# ==============================================================================
|
||||
|
||||
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_LOGIN=4 # No login data in user configuration
|
||||
readonly EX_SFTP_USERNAME=5 # SFTP is only possible when username is root
|
||||
readonly EX_RSA_HOST_KEY=6 # Failed to generate SSH RSA host key
|
||||
readonly EX_ED25519_HOST_KEY=7 # Failed to generate SSH ED25519 host key
|
||||
readonly EX_USER_ADD=8 # Failed to create user account
|
||||
readonly EX_USER_PROFILE=9 # Failed to create user profile
|
||||
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
|
||||
readonly SSH_CONFIG_PATH=/etc/ssh/sshd_config
|
||||
|
||||
# SSH authorized_keys files
|
||||
readonly SSH_AUTHORIZED_KEYS_PATH=/etc/ssh/authorized_keys
|
||||
|
||||
# SSH host keys
|
||||
readonly SSH_HOST_RSA_KEY=/data/ssh_host_rsa_key
|
||||
readonly SSH_HOST_ED25519_KEY=/data/ssh_host_ed25519_key
|
||||
|
||||
# Shell history files
|
||||
readonly ZSH_HISTORY_FILE=/root/.zsh_history
|
||||
readonly ZSH_HISTORY_PERSISTANT_FILE=/data/.zsh_history
|
||||
|
||||
# Debug mode?
|
||||
readonly DEBUG=$(jq --raw-output ".debug" $CONFIG_PATH)
|
||||
|
||||
# ==============================================================================
|
||||
# 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_NO_LOGIN
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_config_requirements() {
|
||||
local authorized_keys
|
||||
local password
|
||||
local username
|
||||
local sftp
|
||||
|
||||
display_status_message 'Ensuring configuration requirements are met'
|
||||
|
||||
username=$(get_config 'username' false)
|
||||
if [[ -z "$username" ]];
|
||||
then
|
||||
display_error_message \
|
||||
'Setting a username in the mandatory!' "$EX_NO_USERNAME"
|
||||
fi
|
||||
|
||||
authorized_keys=$(get_config 'authorized_keys' true)
|
||||
password=$(get_config 'password' false)
|
||||
if [[ -z "$authorized_keys" ]] && [[ -z "$password" ]];
|
||||
then
|
||||
display_error_message \
|
||||
'Configuring a password or authorized keys is mandatory!' \
|
||||
"$EX_NO_LOGIN"
|
||||
fi
|
||||
|
||||
sftp=$(get_config 'sftp' false)
|
||||
if [[ "$sftp" == "true" ]] && [[ "$username" != "root" ]];
|
||||
then
|
||||
display_error_message \
|
||||
'You can only enable SFTP when the username is set to "root"' \
|
||||
"$EX_SFTP_USERNAME"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Ensures all SSH host keys exists, if not, it will create them
|
||||
# Globals:
|
||||
# $EX_ED25519_HOST_KEY
|
||||
# $EX_RSA_HOST_KEY
|
||||
# $SSH_HOST_ED25519_KEY
|
||||
# $SSH_HOST_RSA_KEY
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_host_keys_exist() {
|
||||
display_debug_message 'Ensuring SSH host keys exists'
|
||||
|
||||
if [[ ! -f "$SSH_HOST_RSA_KEY" ]];
|
||||
then
|
||||
display_status_message 'Generating RSA host key'
|
||||
command ssh-keygen -t rsa -f "$SSH_HOST_RSA_KEY" -N "" || \
|
||||
display_error_message 'Failed to generate RSA host key' \
|
||||
"$EX_RSA_HOST_KEY"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SSH_HOST_ED25519_KEY" ]];
|
||||
then
|
||||
display_status_message 'Generating ED25519 host key'
|
||||
command ssh-keygen -t ed25519 -f "$SSH_HOST_ED25519_KEY" -N "" || \
|
||||
display_error_message 'Failed to generate ED25519 host key' \
|
||||
"$EX_ED25519_HOST_KEY"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Creates a user account that is used to log in
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
setup_user() {
|
||||
local username
|
||||
|
||||
username=$(get_config 'username' false)
|
||||
username=${username,,}
|
||||
|
||||
if [[ "$username" != "root" ]];
|
||||
then
|
||||
display_status_message "Creating user to use for login"
|
||||
(command adduser -D "$username" -s "/bin/sh" && \
|
||||
command adduser "$username" wheel) || \
|
||||
display_error_message 'Failed creating an user account for login' \
|
||||
"$EX_USER_ADD"
|
||||
|
||||
echo 'exec sudo su -l' > "/home/$username/.profile" || \
|
||||
display_error_message 'Failed configuring user profile' \
|
||||
"$EX_USER_PROFILE"
|
||||
|
||||
command sed -i "s/AllowUsers\ .*/AllowUsers\ $username/" \
|
||||
"$SSH_CONFIG_PATH"
|
||||
else
|
||||
display_status_message 'WARNING! username = root, this is a bad idea!'
|
||||
command sed -i "s/PermitRootLogin\ .*/PermitRootLogin\ yes/" \
|
||||
"$SSH_CONFIG_PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets up the authorized keys
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
setup_authorized_keys() {
|
||||
local authorized_keys
|
||||
|
||||
authorized_keys=$(get_config 'authorized_keys' true)
|
||||
|
||||
if [[ ! -z "$authorized_keys" ]];
|
||||
then
|
||||
display_status_message 'Setting up authorized_keys'
|
||||
|
||||
display_debug_message 'Adding authorized keys to file'
|
||||
while read -r key;
|
||||
do
|
||||
display_debug_message "Adding public key: $key"
|
||||
echo "$key" >> "$SSH_AUTHORIZED_KEYS_PATH"
|
||||
done <<< "$authorized_keys"
|
||||
else
|
||||
display_status_message 'Login using public/private keypair is disabled.'
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets up password authentication
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
setup_password_authentication() {
|
||||
local password
|
||||
local username
|
||||
|
||||
password=$(get_config 'password' false)
|
||||
username=$(get_config 'username' false)
|
||||
if [[ ! -z "$password" ]]; then
|
||||
display_status_message 'Setting up and enabling password login'
|
||||
|
||||
echo "$username:$password" | chpasswd 2&> /dev/null
|
||||
command sed -i "s/PasswordAuthentication.*/PasswordAuthentication\ yes/" \
|
||||
"$SSH_CONFIG_PATH"
|
||||
else
|
||||
echo "$username:$username" | chpasswd 2&> /dev/null
|
||||
display_status_message 'Login using a password is disabled'
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configures the SSHd port
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
configure_port() {
|
||||
local port
|
||||
|
||||
port=$(get_config 'port' false)
|
||||
if [[ ! -z "$port" ]];
|
||||
then
|
||||
display_status_message "Setting SSH port to: $port"
|
||||
command sed -i "s/Port\ .*/Port\ $port/" "$SSH_CONFIG_PATH"
|
||||
else
|
||||
display_status_message 'Setting SSH port to: 22'
|
||||
command sed -i "s/Port\ .*/Port\ 22/" "$SSH_CONFIG_PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configures SFTP access
|
||||
# Globals:
|
||||
# None
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
configure_sftp() {
|
||||
local sftp
|
||||
|
||||
sftp=$(get_config 'sftp' false)
|
||||
if [[ "$sftp" == "true" ]];
|
||||
then
|
||||
display_status_message "SFTP access is enabled"
|
||||
else
|
||||
display_status_message "SFTP access is disabled"
|
||||
command sed -i '/Subsystem sftp/s/^/#/g' "$SSH_CONFIG_PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Link a set of common used directories in the home folder
|
||||
# Globals:
|
||||
# None
|
||||
# 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:
|
||||
# None
|
||||
# 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_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:
|
||||
# None
|
||||
# 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
|
||||
# Arguments:
|
||||
# None
|
||||
# Returns:
|
||||
# None
|
||||
# ------------------------------------------------------------------------------
|
||||
start_ssh_server() {
|
||||
display_status_message 'Starting SSH daemon'
|
||||
|
||||
if [[ "$DEBUG" == "true" ]];
|
||||
then
|
||||
command /usr/sbin/sshd -D -d -e < /dev/null
|
||||
else
|
||||
command /usr/sbin/sshd -D -e < /dev/null
|
||||
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
|
||||
ensure_host_keys_exist
|
||||
|
||||
setup_user
|
||||
setup_authorized_keys
|
||||
setup_password_authentication
|
||||
|
||||
configure_port
|
||||
configure_sftp
|
||||
|
||||
link_common_directories
|
||||
persist_shell_history
|
||||
|
||||
install_packages
|
||||
run_init_commands
|
||||
|
||||
start_ssh_server
|
||||
exit "$EX_OK"
|
||||
}
|
||||
main
|
|
@ -1,71 +0,0 @@
|
|||
# Basics
|
||||
# ===================
|
||||
Port 22
|
||||
AddressFamily any
|
||||
TCPKeepAlive no
|
||||
ClientAliveInterval 600
|
||||
ClientAliveCountMax 3
|
||||
UseDNS yes
|
||||
|
||||
# Loggin
|
||||
# ===================
|
||||
SyslogFacility AUTH
|
||||
LogLevel VERBOSE
|
||||
|
||||
# Security
|
||||
# ===================
|
||||
Protocol 2
|
||||
StrictModes yes
|
||||
HostKey /data/ssh_host_rsa_key
|
||||
HostKey /data/ssh_host_ed25519_key
|
||||
|
||||
# Cryptography
|
||||
# ===================
|
||||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
|
||||
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
|
||||
|
||||
# Authentication
|
||||
# ===================
|
||||
LoginGraceTime 120
|
||||
MaxAuthTries 6
|
||||
MaxSessions 10
|
||||
MaxStartups 10:30:100
|
||||
PermitRootLogin no
|
||||
AllowUsers root
|
||||
PubkeyAuthentication yes
|
||||
IgnoreRhosts yes
|
||||
HostbasedAuthentication no
|
||||
IgnoreUserKnownHosts no
|
||||
PermitEmptyPasswords no
|
||||
ChallengeResponseAuthentication no
|
||||
PasswordAuthentication no
|
||||
AuthorizedKeysFile /etc/ssh/authorized_keys
|
||||
|
||||
|
||||
# Environment
|
||||
# ===================
|
||||
PermitUserEnvironment no
|
||||
|
||||
# Forwarding / Tunnel
|
||||
# ===================
|
||||
X11Forwarding no
|
||||
X11DisplayOffset 10
|
||||
X11UseLocalhost yes
|
||||
PermitTunnel no
|
||||
AllowTcpForwarding no
|
||||
AllowAgentForwarding no
|
||||
GatewayPorts no
|
||||
|
||||
# Messages
|
||||
# ===================
|
||||
Banner none
|
||||
PrintMotd yes
|
||||
|
||||
# SFTP
|
||||
=====================
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
|
||||
# Misc
|
||||
# ===================
|
||||
AcceptEnv LANG LC_*
|
|
@ -1 +0,0 @@
|
|||
%wheel ALL=(ALL) NOPASSWD: ALL
|
Binary file not shown.
Before Width: | Height: | Size: 121 KiB |
|
@ -1,14 +0,0 @@
|
|||
# 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
|
|
@ -1,21 +0,0 @@
|
|||
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" ]
|
|
@ -1,248 +1,7 @@
|
|||
# Hass.io Add-on: Terminal
|
||||
# Community Hass.io Add-on: Terminal
|
||||
|
||||
![Project Stage][project-stage-shield]
|
||||
![Maintenance][maintenance-shield]
|
||||
![Awesome][awesome-shield]
|
||||
[![License][license-shield]](LICENSE.md)
|
||||
This is just a configuration stub to make the Hass.io repository work.
|
||||
|
||||
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.
|
||||
The add-on itself can be found at the following URL:
|
||||
|
||||

|
||||
|
||||
## 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": "changeme",
|
||||
"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
|
||||
https://github.com/hassio-addons/addon-terminal
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"slug": "terminal",
|
||||
"description": "Terminal access to your Home Assistant instance via the web",
|
||||
"url": "https://github.com/hassio-addons/repository/tree/master/terminal",
|
||||
"url": "https://github.com/hassio-addons/addon-terminal",
|
||||
"webui": "http://[HOST]:[PORT:7681]",
|
||||
"startup": "services",
|
||||
"boot": "auto",
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
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
|
|
@ -1,88 +0,0 @@
|
|||
# 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
|
|
@ -1,101 +0,0 @@
|
|||
#!/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
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
_ _ _____ ____
|
||||
| | | | |_ _/ __ \
|
||||
| |__| | __ _ ___ ___ | || | | |
|
||||
| __ |/ _` / __/ __| | || | | |
|
||||
| | | | (_| \__ \__ \_ _| || |__| |
|
||||
|_| |_|\__,_|___/___(_)_____\____/
|
||||
|
||||
|
||||
Our Cli:
|
||||
$ hassio help
|
||||
|
|
@ -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
|
Binary file not shown.
Before Width: | Height: | Size: 89 KiB |
Loading…
Add table
Add a link
Reference in a new issue