From 5d9b2966fc5bae7961db274f457decf236057ef4 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 29 Jul 2020 01:04:45 +0200 Subject: [PATCH] :tada: Initial add-on code --- .editorconfig | 19 ++ .github/CODEOWNERS | 4 + .github/FUNDING.yml | 4 + .github/ISSUE_TEMPLATE.md | 20 ++ .github/PULL_REQUEST_TEMPLATE.md | 9 + .github/autolabeler.yml | 2 + .github/config.yml | 50 +++++ .github/invite-contributors.yml | 10 + .github/lock.yml | 20 ++ .github/move.yml | 20 ++ .github/no-response.yml | 13 ++ .github/potential-duplicates.yml | 14 ++ .github/settings.yml | 150 +++++++++++++++ .github/stale.yml | 61 ++++++ .github/support.yml | 22 +++ .gitignore | 0 .gitlab-ci.yml | 13 ++ .mdlrc | 1 + .yamllint | 66 +++++++ CODE_OF_CONDUCT.md | 74 +++++++ CONTRIBUTING.md | 29 +++ LICENSE.md | 21 ++ README.md | 125 ++++++++++++ vscode-remote/.README.j2 | 69 +++++++ vscode-remote/DOCS.md | 180 ++++++++++++++++++ vscode-remote/Dockerfile | 107 +++++++++++ vscode-remote/build.json | 7 + vscode-remote/config.json | 37 ++++ vscode-remote/icon.png | Bin 0 -> 4604 bytes vscode-remote/logo.png | Bin 0 -> 62695 bytes vscode-remote/requirements.txt | 2 + .../rootfs/etc/cont-init.d/mosquitto.sh | 27 +++ vscode-remote/rootfs/etc/cont-init.d/mysql.sh | 25 +++ vscode-remote/rootfs/etc/cont-init.d/ssh.sh | 80 ++++++++ vscode-remote/rootfs/etc/cont-init.d/user.sh | 66 +++++++ vscode-remote/rootfs/etc/motd | 11 ++ .../rootfs/etc/services.d/ssh/finish | 9 + vscode-remote/rootfs/etc/services.d/ssh/run | 24 +++ vscode-remote/rootfs/etc/ssh/authorized_keys | 0 vscode-remote/rootfs/etc/ssh/sshd_config | 16 ++ vscode-remote/rootfs/root/.zshrc | 103 ++++++++++ vscode-remote/rootfs/usr/bin/hassio | 3 + 42 files changed, 1513 insertions(+) create mode 100755 .editorconfig create mode 100644 .github/CODEOWNERS create mode 100644 .github/FUNDING.yml create mode 100755 .github/ISSUE_TEMPLATE.md create mode 100755 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/autolabeler.yml create mode 100644 .github/config.yml create mode 100644 .github/invite-contributors.yml create mode 100644 .github/lock.yml create mode 100644 .github/move.yml create mode 100644 .github/no-response.yml create mode 100644 .github/potential-duplicates.yml create mode 100644 .github/settings.yml create mode 100644 .github/stale.yml create mode 100644 .github/support.yml create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .mdlrc create mode 100644 .yamllint create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 vscode-remote/.README.j2 create mode 100644 vscode-remote/DOCS.md create mode 100755 vscode-remote/Dockerfile create mode 100644 vscode-remote/build.json create mode 100755 vscode-remote/config.json create mode 100644 vscode-remote/icon.png create mode 100644 vscode-remote/logo.png create mode 100644 vscode-remote/requirements.txt create mode 100644 vscode-remote/rootfs/etc/cont-init.d/mosquitto.sh create mode 100644 vscode-remote/rootfs/etc/cont-init.d/mysql.sh create mode 100644 vscode-remote/rootfs/etc/cont-init.d/ssh.sh create mode 100644 vscode-remote/rootfs/etc/cont-init.d/user.sh create mode 100755 vscode-remote/rootfs/etc/motd create mode 100644 vscode-remote/rootfs/etc/services.d/ssh/finish create mode 100644 vscode-remote/rootfs/etc/services.d/ssh/run create mode 100644 vscode-remote/rootfs/etc/ssh/authorized_keys create mode 100644 vscode-remote/rootfs/etc/ssh/sshd_config create mode 100755 vscode-remote/rootfs/root/.zshrc create mode 100755 vscode-remote/rootfs/usr/bin/hassio diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..7a12570 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +ident_size = 4 + +[*.md] +ident_size = 2 +trim_trailing_whitespace = false + +[*.json] +ident_size = 2 + +[{.gitignore,.gitkeep,.editorconfig}] +ident_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3fbad49 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# Require maintainer's :+1: for changes to the .github/ repo-config files +# mainly due to https://github.com/probot/settings privilege escalation +.github/* @frenck +.gitlab-ci.yml @frenck diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7f95bd4 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +--- +github: frenck +patreon: frenck +custom: https://frenck.dev/donate/ diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100755 index 0000000..544da8f --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,20 @@ +# Problem/Motivation + +> (Why the issue was filed) + +## Expected behavior + +> (What you expected to happen) + +## Actual behavior + +> (What actually happened) + +## Steps to reproduce + +> (How can someone else make/see it happen) + +## Proposed changes + +> (If you have a proposed change, workaround or fix, +> describe the rationale behind it) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100755 index 0000000..cbd529a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +# Proposed Changes + +> (Describe the changes and rationale behind them) + +## Related Issues + +> ([Github link][autolink-references] to related issues or pull requests) + +[autolink-references]: https://help.github.com/articles/autolinked-references-and-urls/ \ No newline at end of file diff --git a/.github/autolabeler.yml b/.github/autolabeler.yml new file mode 100644 index 0000000..3ce5703 --- /dev/null +++ b/.github/autolabeler.yml @@ -0,0 +1,2 @@ +--- +"Type: Documentation": ["*.md", "*.j2"] diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000..f5828bb --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,50 @@ +--- +# Configuration for request-info - https://github.com/behaviorbot/request-info + +# *OPTIONAL* Comment to reply with +# Can be either a string : +requestInfoReplyComment: + - "We would appreciate it if you could provide us with more info about this issue/pr!" + - "Hmmm... That issue/PR is kinda low on text. Could you please provide some more content?" + +# *OPTIONAL* default titles to check against for lack of descriptiveness +# MUST BE ALL LOWERCASE +requestInfoDefaultTitles: [] + +# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given +requestInfoLabelToAdd: "Incomplete" + +# *OPTIONAL* Require Pull Requests to contain more information than what is provided in the PR template +# Will fail if the pull request's body is equal to the provided template +checkPullRequestTemplate: true + +# *OPTIONAL* Only warn about insufficient information on these events type +# Keys must be lowercase. Valid values are 'issue' and 'pullRequest' +requestInfoOn: + pullRequest: true + issue: true + +# *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on +# keys must be GitHub usernames +requestInfoUserstoExclude: [] + +# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome + +# Comment to be posted to on first time issues +newIssueWelcomeComment: > + :wave: Thanks for opening your first issue here! + If you're reporting a :bug: bug, please make sure you include steps to reproduce it. + Also, logs, error messages and information about your hardware might be useful. + +# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome + +# Comment to be posted to on PRs from first time contributors in your repository +newPRWelcomeComment: > + :sparkling_heart: Thanks for opening this pull request! :sparkling_heart: + If your PR gets accepted and merged in, we will invite you to the project :tada: + +# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge + +# Comment to be posted to on pull requests merged by a first time user +firstPRMergeComment: > + Congrats on merging your first pull request! :tada::tada::tada: diff --git a/.github/invite-contributors.yml b/.github/invite-contributors.yml new file mode 100644 index 0000000..25eb31a --- /dev/null +++ b/.github/invite-contributors.yml @@ -0,0 +1,10 @@ +--- +# If true, this will add new contributors as outside collaborators +# to the repo their PR was merged in. Team name is ignored if this +# flag is set to true. +isOutside: false + +# Specify team name to add new contributors to a specific team +# within your organization. +# Use team name or team-name-slug +team: Contributors diff --git a/.github/lock.yml b/.github/lock.yml new file mode 100644 index 0000000..4b1e816 --- /dev/null +++ b/.github/lock.yml @@ -0,0 +1,20 @@ +--- +# Configuration for lock-threads - https://github.com/dessant/lock-threads +# Number of days of inactivity before a closed issue or pull request is locked +daysUntilLock: 30 + +# Comment to post before locking. Set to `false` to disable +lockComment: > + This thread has been automatically locked because it has not had recent + activity. Please open a new issue for related bugs and link to relevant + comments in this thread. + +# Issues or pull requests with these labels will not be locked +# exemptLabels: +# - no-locking + +# Limit to only `issues` or `pulls` +# only: issues + +# Add a label when locking. Set to `false` to disable +lockLabel: false diff --git a/.github/move.yml b/.github/move.yml new file mode 100644 index 0000000..0c2276a --- /dev/null +++ b/.github/move.yml @@ -0,0 +1,20 @@ +--- +# Delete the command comment when it contains no other content +deleteCommand: true + +# Close the source issue after moving +closeSourceIssue: true + +# Lock the source issue after moving +lockSourceIssue: true + +# Mention issue and comment authors +mentionAuthors: true + +# Preserve mentions in the issue content +keepContentMentions: false + +# Set custom aliases for targets +# aliases: +# r: repo +# or: owner/repo diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000..bb9f0f2 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,13 @@ +--- +# Configuration for probot-no-response - https://github.com/probot/no-response +# Number of days of inactivity before an Issue is closed for lack of response +daysUntilClose: 14 +# Label requiring a response +responseRequiredLabel: "Status: Awaiting response" +# Comment to post when closing an Issue for lack of response. Set to `false` to disable +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. diff --git a/.github/potential-duplicates.yml b/.github/potential-duplicates.yml new file mode 100644 index 0000000..00c7c0f --- /dev/null +++ b/.github/potential-duplicates.yml @@ -0,0 +1,14 @@ +--- +# Label name and color to set, when potential duplicates are detected +issueLabel: "Potential duplicate" +labelColor: e6e6e6 + +# If similarity is higher than this threshold, issue will be marked as duplicate +threshold: 0.70 + +# Comment to post when potential duplicates are detected +referenceComment: > + Potential duplicates found: + {{#issues}} + - [#{{ number }}] {{ title }} ({{ accuracy }}%) + {{/issues}} diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..0b13122 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,150 @@ +--- +repository: + description: "VSCode Remote - Home Assistant Community Add-ons" + homepage: https://addons.community + topics: vscode, remote, ssh, addon, addons, home-assistant, homeassistant + private: false + has_issues: true + has_projects: false + has_wiki: false + has_downloads: false + default_branch: master + allow_squash_merge: true + allow_merge_commit: false + allow_rebase_merge: true +labels: + # Priority labels + - name: "Priority: Critical" + color: ee0701 + description: "This should be dealt with ASAP. Not fixing this issue would be a serious error." + - name: "Priority: High" + color: b60205 + description: "After critical issues are fixed, these should be dealt with before any further issues." + - name: "Priority: Medium" + color: 0e8a16 + description: "This issue may be useful, and needs some attention." + - name: "Priority: Low" + color: e4ea8a + description: "Nice addition, maybe... someday..." + + # Type labels + - name: "Type: Bug" + color: ee0701 + description: "Inconsistencies or issues which will cause a problem for users or implementors." + - name: "Type: Documentation" + color: 0052cc + description: "Solely about the documentation of the project." + - name: "Type: Enhancement" + color: 1d76db + description: "Enhancement of the code, not introducing new features." + - name: "Type: Feature" + color: 0e8a16 + description: "New features or options." + - name: "Type: Support" + color: 5319e7 + description: "Marks an issue as a support ticket." + - name: "Type: Discussion" + color: d4c5f9 + description: "Marks an issue as a generic discussion ticket." + - name: "Type: Maintenance" + color: 2af79e + description: "Generic maintenance tasks, e.g., package updates." + + # Additional markers + - name: "Security" + color: ee0701 + description: "Marks a security issue that needs to be resolved asap." + - name: "Idea" + color: fef2c0 + description: "Marks an idea, which might be excepted and implemented." + - name: "Incomplete" + color: fef2c0 + description: "Marks a PR or issue that is missing information." + - name: "Pull request" + color: fbca04 + description: "There is an PR opened for this issue." + - name: "Accepted" + color: c2e0c6 + description: "This issue or PR has been accepted." + - name: "Declined" + color: f9d0c4 + description: "This issue or PR has been declined." + - name: "Potential duplicate" + color: e6e6e6 + description: "This issue has been automatically marked as a potential duplicate." + + # Ongoing Status labels + - name: "Status: Triage" + color: fbca04 + description: "This issue needs to be triaged." + - name: "Status: On hold" + color: cccccc + description: "Issue or PR that has been placed on hold for now." + - name: "Status: In progress" + color: fbca04 + description: "Issue is currently being resolved by a developer." + - name: "Status: Stale" + color: fef2c0 + description: "There has not been activity on this issue or PR for quite some time." + - name: "Status: Awaiting response" + color: fef2c0 + description: "Issue or PR awaits response from the creator." + - name: "Status: Blocked" + color: fef2c0 + description: "Progress on this issue is currently not possible." + + # Closing status labels + - name: "Closed: Known limitation" + color: e6e6e6 + description: "Issue is closed, it is a known limitation." + - name: "Closed: Expected behavior" + color: e6e6e6 + description: "Issues is closed, it is expected behavior." + - name: "Closed: Duplicate" + color: e6e6e6 + description: "Issue is closed, duplicate of an existing issue." + - name: "Closed: Invalid" + color: e6e6e6 + description: "Issue is closed, marked as not a valid issue (e.g., an user error)." + - name: "Closed: Wrong repository" + color: e6e6e6 + description: "Issue is closed, was created in the wrong repository." + - name: "Closed: Won't Fix" + color: e6e6e6 + description: "Issue is closed, it won't be fixed." + - name: "Closed: Done" + color: c2e0c6 + description: "Issue closed, work on this issue has been marked complete." + + # Others + - name: "Beginner Friendly" + color: 0e8a16 + description: "Good first issue for people wanting to contribute to the project." + - name: "Help wanted" + color: 0e8a16 + description: "We need some extra helping hands or expertise in order to resolve this." + - name: "Hacktoberfest" + description: "Issues/PRs are participating in the Hacktoberfest" + color: fbca04 + +branches: + - name: master + protection: + required_pull_request_reviews: + # required_approving_review_count: 1 + dismiss_stale_reviews: true + require_code_owner_reviews: true + dismissal_restrictions: + users: [] + teams: + - Admins + - Masters + required_status_checks: + strict: false + contexts: [] + enforce_admins: false + restrictions: + users: [] + teams: + - Admins + - Masters diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..36938bb --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,61 @@ +--- +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale Issue or Pull Request is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 7 + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - "Status: On hold" + - "Status: In progress" + - "Status: Awaiting response" + - "Status: Blocked" + - "Idea" + - "Security" + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Label to use when marking as stale +staleLabel: "Status: Stale" + +# Comment to post when marking as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +# Comment to post when removing the stale label. +# unmarkComment: > +# Your comment here. +unmarkComment: false + +# Comment to post when closing a stale Issue or Pull Request. +# closeComment: > +# Your comment here. +closeComment: false + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 + +# Limit to only `issues` or `pulls` +only: issues + +# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': +# pulls: +# daysUntilStale: 30 +# markComment: > +# This pull request has been automatically marked as stale because it has not had +# recent activity. It will be closed if no further activity occurs. Thank you +# for your contributions. + +# issues: +# exemptLabels: +# - confirmed diff --git a/.github/support.yml b/.github/support.yml new file mode 100644 index 0000000..27e688f --- /dev/null +++ b/.github/support.yml @@ -0,0 +1,22 @@ +--- +# Configuration for support-requests - https://github.com/dessant/support-requests + +# Label used to mark issues as support requests +supportLabel: "Type: Support" + +# Comment to post on issues marked as support requests. Add a link +# to a support page, or set to `false` to disable +supportComment: > + :wave: We use the issue tracker exclusively for bug reports and feature requests. + However, this issue appears to be a support request. Please use our + support channels to get help with the project. + + Head over to the + [Home Assistant community forum](https://community.home-assistant.io/?u=frenck) + or join our [Discord](https://discord.me/hassioaddons) chat. + +# Close issues marked as support requests +close: true + +# Lock issues marked as support requests +lock: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..52cb2cc --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,13 @@ +--- +include: https://raw.githubusercontent.com/hassio-addons/organization/master/gitlabci/addon.yml + +variables: + ADDON_GITHUB_REPO: "hassio-addons/addon-vscode-remote" + ADDON_SLUG: "vscode-remote" + ADDON_TARGET: "vscode-remote" + + ADDON_AARCH64_BASE: "hassioaddons/debian-base-aarch64:3.2.1" + ADDON_AMD64_BASE: "hassioaddons/debian-base-amd64:3.2.1" + ADDON_ARMHF_BASE: "hassioaddons/debian-base-armhf:3.2.1" + ADDON_ARMV7_BASE: "hassioaddons/debian-base-armv7:3.2.1" + ADDON_I386_BASE: "hassioaddons/debian-base-i386:3.2.1" diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 0000000..2b0128d --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +rules "~MD024" \ No newline at end of file diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..f4bc5a4 --- /dev/null +++ b/.yamllint @@ -0,0 +1,66 @@ +--- +rules: + braces: + level: error + min-spaces-inside: 0 + max-spaces-inside: 1 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + brackets: + level: error + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + colons: + level: error + max-spaces-before: 0 + max-spaces-after: 1 + commas: + level: error + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + comments: + level: error + require-starting-space: true + min-spaces-from-content: 2 + comments-indentation: + level: error + document-end: + level: error + present: false + document-start: + level: error + present: true + empty-lines: + level: error + max: 1 + max-start: 0 + max-end: 1 + hyphens: + level: error + max-spaces-after: 1 + indentation: + level: error + spaces: 2 + indent-sequences: true + check-multi-line-strings: false + key-duplicates: + level: error + line-length: + ignore: | + .github/support.yml + level: warning + max: 120 + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + new-line-at-end-of-file: + level: error + new-lines: + level: error + type: unix + trailing-spaces: + level: error + truthy: + level: error diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0ac232b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Code of conduct + +## Our pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our standards + +Examples of behavior that contributes to creating a positive environment +include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention + or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or + electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate + in a professional setting + +## Our responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project lead at frenck@addons.community. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project lead is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fdf2072 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish +to make via issue, email, or any other method with the owners of this repository +before making a change. + +Please note we have a code of conduct, please follow it in all your interactions +with the project. + +## Issues and feature requests + +You've found a bug in the source code, a mistake in the documentation or maybe +you'd like a new feature? You can help us by submitting an issue to our +[GitHub Repository][github]. Before you create an issue, make sure you search +the archive, maybe your question was already answered. + +Even better: You could submit a pull request with a fix / new feature! + +## Pull request process + +1. Search our repository for open or closed [pull requests][prs] that relates + to your submission. You don't want to duplicate effort. + +1. You may merge the pull request in once you have the sign-off of two other + developers, or if you do not have permission to do that, you may request + the second reviewer to merge it for you. + +[github]: https://github.com/hassio-addons/addon-vscode-remote/issues +[prs]: https://github.com/hassio-addons/addon-vscode-remote/pulls diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..757686e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2020 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b7bb84 --- /dev/null +++ b/README.md @@ -0,0 +1,125 @@ +# Home Assistant Community Add-on: VSCode Remote + +[![GitHub Release][releases-shield]][releases] +![Project Stage][project-stage-shield] +[![License][license-shield]](LICENSE.md) + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] +![Supports i386 Architecture][i386-shield] + +[![GitLab CI][gitlabci-shield]][gitlabci] +![Project Maintenance][maintenance-shield] +[![GitHub Activity][commits-shield]][commits] + +[![Discord][discord-shield]][discord] +[![Community Forum][forum-shield]][forum] + +[![Sponsor Frenck via GitHub Sponsors][github-sponsors-shield]][github-sponsors] + +[![Support Frenck on Patreon][patreon-shield]][patreon] + +VSCode Remote access to Home Assistant. + +## About + +A small add-on to allow to connect a VSCode client into Home Assistant, +so you can access and edit your configuration with a remote Visual Studio +Code instance with ease. + +[:books: Read the full add-on documentation][docs] + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Community Add-ons Discord chat server][discord] for add-on + support and feature requests. +- The [Home Assistant Discord chat server][discord-ha] for general Home + Assistant discussions and questions. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +You could also [open an issue here][issue] GitHub. + +## Contributing + +This is an active open-source project. We are always open to people who want to +use the code or contribute to it. + +We have set up a separate document containing our +[contribution guidelines](CONTRIBUTING.md). + +Thank you for being involved! :heart_eyes: + +## Authors & contributors + +The original setup of this repository is by [Franck Nijhof][frenck]. + +For a full list of all authors and contributors, +check [the contributor's page][contributors]. + +## We have got some Home Assistant add-ons for you + +Want some more functionality to your Home Assistant instance? + +We have created multiple add-ons for Home Assistant. For a full list, check out +our [GitHub Repository][repository]. + +## License + +MIT License + +Copyright (c) 2020 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-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-vscode-remote.svg +[commits]: https://github.com/hassio-addons/addon-vscode-remote/commits/master +[contributors]: https://github.com/hassio-addons/addon-vscode-remote/graphs/contributors +[discord-ha]: https://discord.gg/c5DvZ4e +[discord-shield]: https://img.shields.io/discord/478094546522079232.svg +[discord]: https://discord.me/hassioaddons +[docs]: https://github.com/hassio-addons/addon-vscode-remote/blob/master/vscode-remote/DOCS.md +[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg +[forum]: https://community.home-assistant.io/?u=frenck +[frenck]: https://github.com/frenck +[github-sponsors-shield]: https://frenck.dev/wp-content/uploads/2019/12/github_sponsor.png +[github-sponsors]: https://github.com/sponsors/frenck +[gitlabci-shield]: https://gitlab.com/hassio-addons/addon-vscode-remote/badges/master/pipeline.svg +[gitlabci]: https://gitlab.com/hassio-addons/addon-vscode-remote/pipelines +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg +[issue]: https://github.com/hassio-addons/addon-vscode-remote/issues +[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-vscode-remote.svg +[maintenance-shield]: https://img.shields.io/maintenance/yes/2020.svg +[patreon-shield]: https://frenck.dev/wp-content/uploads/2019/12/patreon.png +[patreon]: https://www.patreon.com/frenck +[project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg +[reddit]: https://reddit.com/r/homeassistant +[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-vscode-remote.svg +[releases]: https://github.com/hassio-addons/addon-vscode-remote/releases +[repository]: https://github.com/hassio-addons/repository diff --git a/vscode-remote/.README.j2 b/vscode-remote/.README.j2 new file mode 100644 index 0000000..1a225ed --- /dev/null +++ b/vscode-remote/.README.j2 @@ -0,0 +1,69 @@ +# Home Assistant Community Add-on: VSCode Remote + +[![Release][release-shield]][release] ![Project Stage][project-stage-shield] ![Project Maintenance][maintenance-shield] + +[![Discord][discord-shield]][discord] [![Community Forum][forum-shield]][forum] + +[![Sponsor Frenck via GitHub Sponsors][github-sponsors-shield]][github-sponsors] + +[![Support Frenck on Patreon][patreon-shield]][patreon] + +VSCode Remote access to Home Assistant + +## About + +A small add-on to allow to connect a VSCode client into Home Assistant, +so you can access and edit your configuration with a remote Visual Studio +Code instance with ease. + +{% if channel == "edge" %} +## WARNING! THIS IS AN EDGE VERSION! + +This Home Assistant Add-ons repository contains edge builds of add-ons. +Edge builds add-ons are based upon the latest development version. + +- They may not work at all. +- They might stop working at any time. +- They could have a negative impact on your system. + +This repository was created for: + +- Anybody willing to test. +- Anybody interested in trying out upcoming add-ons or add-on features. +- Developers. + +If you are more interested in stable releases of our add-ons: + + + +{% endif %} +{% if channel == "beta" %} +## WARNING! THIS IS A BETA VERSION! + +This Home Assistant Add-ons repository contains beta releases of add-ons. + +- They might stop working at any time. +- They could have a negative impact on your system. + +This repository was created for: + +- Anybody willing to test. +- Anybody interested in trying out upcoming add-ons or add-on features. + +If you are more interested in stable releases of our add-ons: + + + +{% endif %} +[discord-shield]: https://img.shields.io/discord/478094546522079232.svg +[discord]: https://discord.me/hassioaddons +[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg +[forum]: https://community.home-assistant.io/?u=frenck +[github-sponsors-shield]: https://frenck.dev/wp-content/uploads/2019/12/github_sponsor.png +[github-sponsors]: https://github.com/sponsors/frenck +[maintenance-shield]: https://img.shields.io/maintenance/yes/2020.svg +[patreon-shield]: https://frenck.dev/wp-content/uploads/2019/12/patreon.png +[patreon]: https://www.patreon.com/frenck +[project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg +[release-shield]: https://img.shields.io/badge/version-{{ version }}-blue.svg +[release]: {{ repo }}/tree/{{ version }} diff --git a/vscode-remote/DOCS.md b/vscode-remote/DOCS.md new file mode 100644 index 0000000..3c1b83b --- /dev/null +++ b/vscode-remote/DOCS.md @@ -0,0 +1,180 @@ +# Home Assistant Community Add-on: VSCode Remote + +A small add-on to allow to connect a VSCode client into Home Assistant, +so you can access and edit your configuration with a remote Visual Studio +Code instance with ease. + +## Installation + +The installation of this add-on is pretty straightforward and not different in +comparison to installing any other Home Assistant add-on. + +1. Search for the "VSCode Remote" add-on in the Supervisor add-on store + and install it. +1. Set a password or add a SSH public key pair to the add-on configuration. +1. Start the "VSCode Remote" add-on. +1. Check the logs of the "VSCode Remote" add-on to see if everything went well. +1. Connect the Visual Studio Code on your desktop with Home Assistant. + +## Configuration + +**Note**: _Remember to restart the add-on when the configuration is changed._ + +Example add-on configuration: + +```yaml +log_level: info +password: '' +authorized_keys: + - ssh-rsa AASDJKJKJFWJFAFLCNALCMLAK234234..... +packages: + - mariadb-client +init_commands: + - ls -la +``` + +**Note**: _This is just an example, don't copy and paste it! Create your own!_ + +### Option: `log_level` + +The `log_level` option controls the level of log output by the addon and can +be changed to be more or less verbose, which might be useful when you are +dealing with an unknown issue. Possible values are: + +- `trace`: Show every detail, like all called internal functions. +- `debug`: Shows detailed debug information. +- `info`: Normal (usually) interesting events. +- `warning`: Exceptional occurrences that are not errors. +- `error`: Runtime errors that do not require immediate action. +- `fatal`: Something went terribly wrong. Add-on becomes unusable. + +Please note that each level automatically includes log messages from a +more severe level, e.g., `debug` also shows `info` messages. By default, +the `log_level` is set to `info`, which is the recommended setting unless +you are troubleshooting. + +### Option: `password` + +Sets the password to log in with. Leaving it empty would disable the possibility +to authenticate with a password. We would highly recommend not to use this +option from a security point of view. + +**Note**: _The password will be checked against HaveIBeenPwned. If it is +listed, the add-on will not start._ + +### 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 key pairs and how to create them. + +**Note**: _Please ensure the keys are specified as a list._ + +### Option: `packages` + +Allows you to specify additional [Debian packages][debian-packages] to be +installed in your shell environment (e.g., Python, PHP, Go). + +**Note**: _Adding many packages will result in a longer start-up +time for the add-on._ + +### Option: `init_commands` + +Customize your VSCode 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. + +#### Option: `i_like_to_be_pwned` + +Adding this option to the add-on configuration allows to you bypass the +HaveIBeenPwned password requirement by setting it to `true`. + +**Note**: _We STRONGLY suggest picking a stronger/safer password instead of +using this option! USE AT YOUR OWN RISK!_ + +## Known issues and limitations + +- "Visual Studio Code is unable to watch for file changes in this large + workspace" (error ENOSPC) + + This issue is caused by your system not having enough file handles, + which causes VSCode to be unable to watch all your files. For HassOS, + currently the only option is to click on the little cog when the + notification appears and tell it to not show again. In case you have + a generic Linux setup (e.g., Ubuntu), follow this guide by Microsoft: + + + +## Changelog & Releases + +This repository keeps a change log using [GitHub's releases][releases] +functionality. The format of the log is based on +[Keep a Changelog][keepchangelog]. + +Releases are based on [Semantic Versioning][semver], and use the format +of ``MAJOR.MINOR.PATCH``. In a nutshell, the version will be incremented +based on the following: + +- ``MAJOR``: Incompatible or major changes. +- ``MINOR``: Backwards-compatible new features and enhancements. +- ``PATCH``: Backwards-compatible bugfixes and package updates. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Community Add-ons Discord chat server][discord] for add-on + support and feature requests. +- The [Home Assistant Discord chat server][discord-ha] for general Home + Assistant discussions and questions. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +You could also [open an issue here][issue] GitHub. + +## Authors & contributors + +The original setup of this repository is by [Franck Nijhof][frenck]. + +For a full list of all authors and contributors, +check [the contributor's page][contributors]. + +## License + +MIT License + +Copyright (c) 2020 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. + +[contributors]: https://github.com/hassio-addons/addon-vscode-remote/graphs/contributors +[discord-ha]: https://discord.gg/c5DvZ4e +[discord]: https://discord.me/hassioaddons +[forum]: https://community.home-assistant.io/?u=frenck +[frenck]: https://github.com/frenck +[issue]: https://github.com/hassio-addons/addon-vscode-remote/issues +[keepchangelog]: http://keepachangelog.com/en/1.0.0/ +[reddit]: https://reddit.com/r/homeassistant +[releases]: https://github.com/hassio-addons/addon-vscode-remote/releases +[semver]: http://semver.org/spec/v2.0.0 +[debian-packages]: https://packages.debian.com diff --git a/vscode-remote/Dockerfile b/vscode-remote/Dockerfile new file mode 100755 index 0000000..f9698ac --- /dev/null +++ b/vscode-remote/Dockerfile @@ -0,0 +1,107 @@ +ARG BUILD_FROM=hassioaddons/debian-base:3.2.1 +# hadolint ignore=DL3006 +FROM ${BUILD_FROM} + +# Confiure locale +ENV \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Copy Python requirements file +COPY requirements.txt /tmp/requirements.txt + +# Setup base system +ARG BUILD_ARCH=amd64 +# hadolint ignore=SC2181 +RUN \ + apt-get update \ + \ + && apt-get install -y --no-install-recommends \ + ack=2.24-1 \ + colordiff=1.0.18-1 \ + git=1:2.20.1-2+deb10u3 \ + iputils-ping=3:20180629-2+deb10u1 \ + locales=2.28-10 \ + mariadb-client=1:10.3.22-0+deb10u1 \ + mosquitto-clients=1.5.7-1+deb10u1 \ + net-tools=1.60+git20180626.aebd88e-1 \ + nmap=7.70+dfsg1-6 \ + openssh-client=1:7.9p1-10+deb10u2 \ + openssh-server=1:7.9p1-10+deb10u2 \ + openssl=1.1.1d-0+deb10u3 \ + pwgen=2.08-1 \ + python3-dev=3.7.3-1 \ + python3=3.7.3-1 \ + wget=1.20.1-1.1 \ + zsh=5.7.1-1 \ + \ + && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ + && locale-gen \ + \ + && curl https://bootstrap.pypa.io/get-pip.py | python3 \ + \ + && curl -L -s -o /usr/bin/ha \ + "https://github.com/home-assistant/cli/releases/download/4.3.0/ha_${BUILD_ARCH}" \ + && chmod a+x /usr/bin/ha \ + \ + && git clone --branch master --single-branch --depth 1 \ + "git://github.com/robbyrussell/oh-my-zsh.git" ~/.oh-my-zsh \ + \ + && git clone --branch master --single-branch --depth 1 \ + "git://github.com/zsh-users/zsh-autosuggestions" \ + ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions \ + && git clone --branch master --single-branch --depth 1 \ + "git://github.com/zsh-users/zsh-syntax-highlighting.git" \ + ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting \ + \ + && sed -i -e "s#bin/bash#bin/zsh#" /etc/passwd \ + \ + && update-alternatives \ + --install /usr/bin/python python /usr/bin/python3 10 \ + \ + && pip3 install --no-cache-dir -r /tmp/requirements.txt \ + \ + && apt-get purge -y --auto-remove \ + python3-dev \ + \ + && find /usr/local/lib/python3.7/ -type d -name tests -depth -exec rm -rf {} \; \ + && find /usr/local/lib/python3.7/ -type d -name test -depth -exec rm -rf {} \; \ + && find /usr/local/lib/python3.7/ -name __pycache__ -depth -exec rm -rf {} \; \ + && find /usr/local/lib/python3.7/ -name "*.pyc" -depth -exec rm -f {} \; \ + \ + && rm -fr \ + /tmp/* \ + /var/{cache,log}/* \ + /var/lib/apt/lists/* + +# Copy root filesystem +COPY rootfs / + +# Build arguments +ARG BUILD_DATE +ARG BUILD_REF +ARG BUILD_VERSION + +# Labels +LABEL \ + io.hass.name="VSCode Remote" \ + io.hass.description="VSCode Remote access to Home Assistant" \ + io.hass.arch="${BUILD_ARCH}" \ + io.hass.type="addon" \ + io.hass.version=${BUILD_VERSION} \ + maintainer="Franck Nijhof " \ + org.opencontainers.image.title="VSCode Remote" \ + org.opencontainers.image.description="VSCode Remote access to Home Assistant" \ + org.opencontainers.image.vendor="Home Assistant Community Add-ons" \ + org.opencontainers.image.authors="Franck Nijhof " \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.url="https://addons.community" \ + org.opencontainers.image.source="https://github.com/hassio-addons/addon-vscode-remote" \ + org.opencontainers.image.documentation="https://github.com/hassio-addons/addon-vscode-remote/blob/master/README.md" \ + org.opencontainers.image.created=${BUILD_DATE} \ + org.opencontainers.image.revision=${BUILD_REF} \ + org.opencontainers.image.version=${BUILD_VERSION} diff --git a/vscode-remote/build.json b/vscode-remote/build.json new file mode 100644 index 0000000..6ed4d60 --- /dev/null +++ b/vscode-remote/build.json @@ -0,0 +1,7 @@ +{ + "build_from": { + "aarch64": "hassioaddons/debian-base-aarch64:3.2.1", + "amd64": "hassioaddons/debian-base-amd64:3.2.1" + }, + "args": {} +} diff --git a/vscode-remote/config.json b/vscode-remote/config.json new file mode 100755 index 0000000..4655d90 --- /dev/null +++ b/vscode-remote/config.json @@ -0,0 +1,37 @@ +{ + "name": "VSCode Remote", + "version": "dev", + "slug": "vscode-remote", + "description": "VSCode Remote access to Home Assistant", + "url": "https://github.com/hassio-addons/addon-vscode-remote", + "startup": "services", + "init": false, + "arch": ["aarch64", "amd64", "armhf", "armv7", "i386"], + "boot": "auto", + "auto_uart": true, + "hassio_api": true, + "hassio_role": "manager", + "homeassistant_api": true, + "map": ["config:rw", "ssl:rw", "addons:rw", "share:rw", "backup:rw"], + "services": ["mysql:want", "mqtt:want"], + "ports": { + "22/tcp": 2222 + }, + "ports_description": { + "22/tcp": "VSCode Remote SSH server port" + }, + "options": { + "password": "", + "authorized_keys": [], + "packages": [], + "init_commands": [] + }, + "schema": { + "log_level": "list(trace|debug|info|notice|warning|error|fatal)?", + "password": "password", + "authorized_keys": ["str"], + "packages": ["str"], + "init_commands": ["str"], + "i_like_to_be_pwned": "bool?" + } +} diff --git a/vscode-remote/icon.png b/vscode-remote/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b3225e44d933efdc7c90fe49c050c651dfd88fc1 GIT binary patch literal 4604 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 /root/.config/mosquitto_sub + + ln -s /root/.config/mosquitto_sub /root/.config/mosquitto_pub + ln -s /root/.config/mosquitto_sub /root/.config/mosquitto_rr +fi diff --git a/vscode-remote/rootfs/etc/cont-init.d/mysql.sh b/vscode-remote/rootfs/etc/cont-init.d/mysql.sh new file mode 100644 index 0000000..8c13258 --- /dev/null +++ b/vscode-remote/rootfs/etc/cont-init.d/mysql.sh @@ -0,0 +1,25 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: VSCode Remote +# Pre-configures the MySQL clients, if the service is available +# ============================================================================== +declare host +declare password +declare port +declare username + +if bashio::services.available "mysql"; then + host=$(bashio::services "mysql" "host") + password=$(bashio::services "mysql" "password") + port=$(bashio::services "mysql" "port") + username=$(bashio::services "mysql" "username") + + mkdir -p /root/.config + { + echo "[client]" + echo "host=${host}" + echo "password=\"${password}\"" + echo "port=${port}" + echo "user=\"${username}\"" + } > /etc/mysql/conf.d/service.cnf +fi diff --git a/vscode-remote/rootfs/etc/cont-init.d/ssh.sh b/vscode-remote/rootfs/etc/cont-init.d/ssh.sh new file mode 100644 index 0000000..30afd15 --- /dev/null +++ b/vscode-remote/rootfs/etc/cont-init.d/ssh.sh @@ -0,0 +1,80 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: VSCode Remote +# Configures the SSH daemon +# ============================================================================== +readonly SSH_AUTHORIZED_KEYS_PATH=/etc/ssh/authorized_keys +readonly SSH_CONFIG_PATH=/etc/ssh/sshd_config +readonly SSH_HOST_ED25519_KEY=/data/ssh_host_ed25519_key +readonly SSH_HOST_RSA_KEY=/data/ssh_host_rsa_key +declare password + +# We require at least a password or an authorized key +if bashio::config.is_empty 'authorized_keys' \ + && bashio::config.is_empty 'password'; +then + bashio::log.fatal + bashio::log.fatal 'Configuration of this add-on is incomplete.' + bashio::log.fatal + bashio::log.fatal 'Please be sure to set a least a password' + bashio::log.fatal 'or at least one authorized key!' + bashio::log.fatal + bashio::log.fatal 'You can configure this using the "password"' + bashio::log.fatal 'or the "authorized_keys" option in the' + bashio::log.fatal 'add-on configuration.' + bashio::log.fatal + bashio::exit.nok +fi + +# Require a secure password +if bashio::config.has_value 'password' \ + && ! bashio::config.true 'i_like_to_be_pwned'; then + bashio::config.require.safe_password 'password' +fi + +# Warn about password login +if bashio::config.has_value 'password'; then + bashio::log.warning + bashio::log.warning \ + 'Logging in with a SSH password is security wise, a bad idea!' + bashio::log.warning 'Please, consider using a public/private key pair.' + bashio::log.warning 'What is this? https://kb.iu.edu/d/aews' + bashio::log.warning +fi + +# Generate host keys +if ! bashio::fs.file_exists "${SSH_HOST_RSA_KEY}"; then + bashio::log.notice 'RSA host key missing, generating one...' + + ssh-keygen -t rsa -f "${SSH_HOST_RSA_KEY}" -N "" \ + || bashio::exit.nok 'Failed to generate RSA host key' +fi + +if ! bashio::fs.file_exists "${SSH_HOST_ED25519_KEY}"; then + bashio::log.notice 'ED25519 host key missing, generating one...' + ssh-keygen -t ed25519 -f "${SSH_HOST_ED25519_KEY}" -N "" \ + || bashio::exit.nok 'Failed to generate ED25519 host key' +fi + +# We need to set a password for the user account +if bashio::config.has_value 'password'; then + password=$(bashio::config 'password') +else + # Use a random password in case none is set + password=$(pwgen 64 1) +fi +chpasswd <<< "root:${password}" 2&> /dev/null + +# Sets up the authorized SSH keys +if bashio::config.has_value 'authorized_keys'; then + while read -r key; do + echo "${key}" >> "${SSH_AUTHORIZED_KEYS_PATH}" + done <<< "$(bashio::config 'authorized_keys')" +fi + +# Enable password authentication when password is set +if bashio::config.has_value 'ssh.password'; then + sed -i "s/PasswordAuthentication.*/PasswordAuthentication\\ yes/" \ + "${SSH_CONFIG_PATH}" \ + || bashio::exit.nok 'Failed to setup SSH password authentication' +fi diff --git a/vscode-remote/rootfs/etc/cont-init.d/user.sh b/vscode-remote/rootfs/etc/cont-init.d/user.sh new file mode 100644 index 0000000..86754c9 --- /dev/null +++ b/vscode-remote/rootfs/etc/cont-init.d/user.sh @@ -0,0 +1,66 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: VSCode Remote +# Persists user settings and installs custom user packages. +# ============================================================================== +readonly GIT_USER_PATH=/data/git +readonly SSH_USER_PATH=/data/.ssh +readonly ZSH_HISTORY_FILE=/root/.zsh_history +readonly ZSH_HISTORY_PERSISTANT_FILE=/data/.zsh_history + +# Store SSH settings in add-on data folder +if ! bashio::fs.directory_exists "${SSH_USER_PATH}"; then + mkdir -p "${SSH_USER_PATH}" \ + || bashio::exit.nok 'Failed to create a persistent .ssh folder' + + chmod 700 "${SSH_USER_PATH}" \ + || bashio::exit.nok \ + 'Failed setting permissions on persistent .ssh folder' +fi +ln -s "${SSH_USER_PATH}" ~/.ssh + +# Sets up ZSH shell +touch "${ZSH_HISTORY_PERSISTANT_FILE}" \ + || bashio::exit.nok 'Failed creating a persistent ZSH history file' + +chmod 600 "$ZSH_HISTORY_PERSISTANT_FILE" \ + || bashio::exit.nok \ + 'Failed setting the correct permissions to the ZSH history file' + +ln -s -f "$ZSH_HISTORY_PERSISTANT_FILE" "$ZSH_HISTORY_FILE" \ + || bashio::exit.nok 'Failed linking the persistant ZSH history file' + +# Store user GIT settings in add-on data folder +if ! bashio::fs.directory_exists "${GIT_USER_PATH}"; then + mkdir -p "${GIT_USER_PATH}" \ + || bashio::exit.nok 'Failed to create a persistent git folder' + + chmod 700 "${GIT_USER_PATH}" \ + || bashio::exit.nok \ + 'Failed setting permissions on persistent git folder' +fi + +if ! bashio::fs.file_exists "${GIT_USER_PATH}/.gitconfig"; then + touch "${GIT_USER_PATH}/.gitconfig" \ + || bashio::exit.nok 'Failed to create .gitconfig' +fi +ln -s "${GIT_USER_PATH}/.gitconfig" ~/.gitconfig + +# Install user configured/requested packages +if bashio::config.has_value 'packages'; then + apt update \ + || bashio::exit.nok 'Failed updating Ubuntu packages repository indexes' + + for package in $(bashio::config 'packages'); do + apt-get install -y "$package" \ + || bashio::exit.nok "Failed installing package ${package}" + done +fi + +# Executes user configured/requested commands on startup +if bashio::config.has_value 'init_commands'; then + while read -r cmd; do + eval "${cmd}" \ + || bashio::exit.nok "Failed executing init command: ${cmd}" + done <<< "$(bashio::config 'init_commands')" +fi diff --git a/vscode-remote/rootfs/etc/motd b/vscode-remote/rootfs/etc/motd new file mode 100755 index 0000000..df098a9 --- /dev/null +++ b/vscode-remote/rootfs/etc/motd @@ -0,0 +1,11 @@ + + _ _ _ _ _ +| | | | /\ (_) | | | | +| |__| | ___ _ __ ___ ___ / \ ___ ___ _ ___| |_ __ _ _ __ | |_ +| __ |/ _ \| '_ ` _ \ / _ \ / /\ \ / __/ __| / __| __/ _` | '_ \| __| +| | | | (_) | | | | | | __/ / ____ \\__ \__ \ \__ \ || (_| | | | | |_ +|_| |_|\___/|_| |_| |_|\___| /_/ \_\___/___/_|___/\__\__,_|_| |_|\__| + + +Our command line: +$ ha help diff --git a/vscode-remote/rootfs/etc/services.d/ssh/finish b/vscode-remote/rootfs/etc/services.d/ssh/finish new file mode 100644 index 0000000..8742dbd --- /dev/null +++ b/vscode-remote/rootfs/etc/services.d/ssh/finish @@ -0,0 +1,9 @@ +#!/usr/bin/execlineb -S0 +# ============================================================================== +# Home Assistant Community Add-on: VSCode Remote +# Take down the S6 supervision tree when the code server fails +# ============================================================================== +if { s6-test ${1} -ne 0 } +if { s6-test ${1} -ne 256 } + +s6-svscanctl -t /var/run/s6/services diff --git a/vscode-remote/rootfs/etc/services.d/ssh/run b/vscode-remote/rootfs/etc/services.d/ssh/run new file mode 100644 index 0000000..7358023 --- /dev/null +++ b/vscode-remote/rootfs/etc/services.d/ssh/run @@ -0,0 +1,24 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: VSCode Remote +# Runs the SSH daemon +# ============================================================================== +declare -a options + +bashio::log.info 'Starting the SSH Daemon for VSCode...' + +# Default options +options+=(-D) +options+=(-e) + +# Enable debug mode on the SSH daemon +if bashio::debug; then + options+=(-d) +fi + +# Ensure needed folders exists +mkdir -p /run/sshd +chmod -R 755 /run/sshd + +# Start the SSH daemon +exec /usr/sbin/sshd "${options[@]}" < /dev/null diff --git a/vscode-remote/rootfs/etc/ssh/authorized_keys b/vscode-remote/rootfs/etc/ssh/authorized_keys new file mode 100644 index 0000000..e69de29 diff --git a/vscode-remote/rootfs/etc/ssh/sshd_config b/vscode-remote/rootfs/etc/ssh/sshd_config new file mode 100644 index 0000000..b77792d --- /dev/null +++ b/vscode-remote/rootfs/etc/ssh/sshd_config @@ -0,0 +1,16 @@ +AcceptEnv LANG LC_* +AllowAgentForwarding yes +AllowTcpForwarding yes +AuthorizedKeysFile /etc/ssh/authorized_keys ~/.ssh/authorized_keys +Banner none +ChallengeResponseAuthentication no +HostKey /data/ssh_host_ed25519_key +HostKey /data/ssh_host_rsa_key +PasswordAuthentication no +PermitRootLogin yes +Port 22 +PrintMotd no +StreamLocalBindUnlink yes +Subsystem sftp /usr/lib/openssh/sftp-server +UsePAM yes +X11Forwarding yes diff --git a/vscode-remote/rootfs/root/.zshrc b/vscode-remote/rootfs/root/.zshrc new file mode 100755 index 0000000..8640e75 --- /dev/null +++ b/vscode-remote/rootfs/root/.zshrc @@ -0,0 +1,103 @@ +# 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 + nmap + pip + python + rsync + zsh-autosuggestions + zsh-syntax-highlighting +) + +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" + +# Home Assistant Core CLI +eval "$(_HASS_CLI_COMPLETE=source_zsh hass-cli)" + +# Home Assistant CLI +source <(ha completion --zsh) + +# Show motd on start +cat /etc/motd diff --git a/vscode-remote/rootfs/usr/bin/hassio b/vscode-remote/rootfs/usr/bin/hassio new file mode 100755 index 0000000..e38eb86 --- /dev/null +++ b/vscode-remote/rootfs/usr/bin/hassio @@ -0,0 +1,3 @@ +#!/usr/bin/env bashio +bashio::log.yellow "The 'hassio' command is deprecated, please use 'ha' instead!" +ha "$@"