diff --git a/{{cookiecutter.project_slug}}/Dockerfile b/{{cookiecutter.project_slug}}/Dockerfile index 2b794af..d747490 100644 --- a/{{cookiecutter.project_slug}}/Dockerfile +++ b/{{cookiecutter.project_slug}}/Dockerfile @@ -24,7 +24,7 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH" RUN set -x; \ groupadd -g $GROUP_ID app && \ useradd --create-home -u $USER_ID -g app -s /bin/bash app && \ - install -o app -g app -d /code "$VIRTUAL_ENV" + install -o app -g app -d /code "$VIRTUAL_ENV" /home/app/.ssh USER app RUN python -m venv "$VIRTUAL_ENV" WORKDIR /code diff --git a/{{cookiecutter.project_slug}}/docker-compose.override.example.yml b/{{cookiecutter.project_slug}}/docker-compose.override.example.yml index d8adfad..3ebe16d 100644 --- a/{{cookiecutter.project_slug}}/docker-compose.override.example.yml +++ b/{{cookiecutter.project_slug}}/docker-compose.override.example.yml @@ -25,7 +25,7 @@ # ports: # - 127.0.0.1:8025:8025 -# PONTSUN CONFIGURATION +# EXTENDED CONFIGURATION (pontsun, SSH access) # ~~~~~~~~~~~~~~~~~~~~~ # # Set up pontsun (https://github.com/liip/pontsun) and start it. Then visit @@ -48,6 +48,9 @@ # SSH_AUTH_SOCK: /ssh-agent # volumes: # - $SSH_AUTH_SOCK:/ssh-agent +# # SSH agent forwarding only works with Linux hosts +# # On Windows and macOS, you have to mount the private key directly: +# # - ~/.ssh/id_rsa:/home/app/.ssh/id_rsa # build: # args: # <<: *x-build-args diff --git a/{{cookiecutter.project_slug}}/fabfile.py b/{{cookiecutter.project_slug}}/fabfile.py index 3d19a40..7c77f46 100644 --- a/{{cookiecutter.project_slug}}/fabfile.py +++ b/{{cookiecutter.project_slug}}/fabfile.py @@ -1,4 +1,5 @@ import functools +import getpass import inspect import os import random @@ -12,6 +13,7 @@ from fabric.connection import Connection from invoke import Exit from invoke.exceptions import UnexpectedExit +from paramiko.ssh_exception import PasswordRequiredException ENVIRONMENTS = { "prod": { @@ -62,9 +64,19 @@ def ensure_absolute_path(path): class CustomConnection(Connection): """ - Add helpers function on Connection + Add helpers function on Connection. + Also automatically prompt for password on connection (when necessary). """ + def open(self): + try: + super().open() + except PasswordRequiredException: + # Prompt for passphrase and try again + prompt = "Enter passphrase for unlocking SSH keys: " + self.connect_kwargs["passphrase"] = getpass.getpass(prompt) + super().open() + @property def site_root(self): return self.config.root @@ -552,10 +564,12 @@ def load_environment(ctx): conf["environment"] = name # So now conf is the ENVIRONMENTS[env] dict plus "environment" pointing to the name # Push them in the context config dict - ctx.config.load_overrides(conf) - # Add the common_settings in there - ctx.conn = CustomConnection(host=conf["host"], inline_ssh_env=True) - ctx.conn.config.load_overrides(conf) + ctx.config.update(conf) + # Create a connection for this environment, + # sharing most of the configuration with the root context + ctx.conn = CustomConnection( + config=ctx.config.clone(), host=conf["host"], inline_ssh_env=True + ) load_environment.__doc__ = ( """Prepare connection and load config for %s environment""" % name