{"id":17422223,"url":"https://github.com/alexzhangs/aws-cfn-vpn","last_synced_at":"2025-08-17T18:33:18.292Z","repository":{"id":42128580,"uuid":"108380654","full_name":"alexzhangs/aws-cfn-vpn","owner":"alexzhangs","description":"AWS CloudFormation Stack for VPN server.","archived":false,"fork":false,"pushed_at":"2024-06-07T14:43:28.000Z","size":2592,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T23:25:42.424Z","etag":null,"topics":["aws","aws-acm","aws-cloudformation","aws-config","aws-custom-resource","aws-lambda","aws-lex","aws-vpc-peering","l2tp","l2tpd","lex","shadowsocks","shadowsocks-libev","shadowsocks-manager","vpn","xl2tpd","xsh","xsh-lib"],"latest_commit_sha":null,"homepage":"https://www.0xbeta.com/aws-cfn-vpn/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexzhangs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-26T08:05:38.000Z","updated_at":"2024-06-02T02:41:59.000Z","dependencies_parsed_at":"2024-03-03T07:25:10.070Z","dependency_job_id":"9a6fc145-85fc-473a-bef0-fc1e10fd1884","html_url":"https://github.com/alexzhangs/aws-cfn-vpn","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/alexzhangs/aws-cfn-vpn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexzhangs%2Faws-cfn-vpn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexzhangs%2Faws-cfn-vpn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexzhangs%2Faws-cfn-vpn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexzhangs%2Faws-cfn-vpn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexzhangs","download_url":"https://codeload.github.com/alexzhangs/aws-cfn-vpn/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexzhangs%2Faws-cfn-vpn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270891786,"owners_count":24663537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-acm","aws-cloudformation","aws-config","aws-custom-resource","aws-lambda","aws-lex","aws-vpc-peering","l2tp","l2tpd","lex","shadowsocks","shadowsocks-libev","shadowsocks-manager","vpn","xl2tpd","xsh","xsh-lib"],"created_at":"2024-10-17T03:13:56.434Z","updated_at":"2025-08-17T18:33:18.247Z","avatar_url":"https://github.com/alexzhangs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GitHub tag](https://img.shields.io/github/v/tag/alexzhangs/aws-cfn-vpn?sort=date)](https://github.com/alexzhangs/aws-cfn-vpn/tags)\n[![GitHub](https://img.shields.io/github/license/alexzhangs/aws-cfn-vpn.svg?style=flat-square)](https://github.com/alexzhangs/aws-cfn-vpn/)\n[![GitHub last commit](https://img.shields.io/github/last-commit/alexzhangs/aws-cfn-vpn.svg?style=flat-square)](https://github.com/alexzhangs/aws-cfn-vpn/commits/master)\n\n[![GitHub issues](https://img.shields.io/github/issues/alexzhangs/aws-cfn-vpn.svg?style=flat-square)](https://github.com/alexzhangs/aws-cfn-vpn/issues)\n[![GitHub pull requests](https://img.shields.io/github/issues-pr/alexzhangs/aws-cfn-vpn.svg?style=flat-square)](https://github.com/alexzhangs/aws-cfn-vpn/pulls)\n\n# aws-cfn-vpn\n\nAWS CloudFormation Stack for VPN services.\n\nThis Repo use AWS CloudFormation to automate the deployment of Shadowsocks\nand L2TPD, and is trying to make the deployment as easy as possible.\n\nAdditionally, it's also deploying\n[shadowsocks-manager](https://github.com/alexzhangs/shadowsocks-manager)\nwhich is a web-based Shadowsocks management tool for multi-user and traffic statistics,\nsupport multi-node and DNS record management through dns-lexicon.\n\n## Screenshots\n\n![stack list](/assets/images/aws-cfn-vpn.png)\n\n## Services List\n\n* Shadowsocks-libev\n* L2TPD\n\n## Features\n\nShadowsocks-libev:\n\n* Users(ports) are managed by\n[shadowsocks-manager](https://github.com/alexzhangs/shadowsocks-manager).\n* Sending the account Email.\n* Multi nodes(across multi AWS accounts).\n* Active/Inactive users and nodes.\n* Heartbeat to detect the port alive on the node.\n* Auto-create the DNS records for the domains of the web console, L2TP,\n  and Shadowsocks nodes in your DNS provider.\n* Auto-sync the node info to shadowsocks-manager.\n* Auto-sync the node IP address to your DNS provider.\n* Traffic statistics on ports and nodes(minimize the impact of\n  node restart).\n* Change node IP address from:\n    * Web console\n    * scheduled job\n    * Amazon Lex chatbot\n    * REST API\n    * AWS SNS message\n* Support v2ray-plugin on node level.\n\nL2TPD:\n\n* User management in the command line.\n\n## Overview\n\nThis stack leverages several other repos to achieve the work, below\ngives an overview of the inside dependency structure. All the internal\ndependencies will be installed automatically except `aws-ec2-ses`.\n\n```\naws-cfn-vpn (github)\n├── aws-cfn-vpc (github)\n├── aws-cfn-vpc-peer-acceptor (github)\n├── aws-cfn-vpc-peer-requester (github)\n├── aws-cfn-config-provider (github)\n├── aws-cfn-vpn-lexbot (github)\n├── shadowsocks-libev-v2ray (dockerhub)\n│   ├── shadowsocks-libev (dockerhub)\n│   ├── v2ray-plugin (github)\n|   └── acme.sh (github)\n├── shadowsocks-manager (dockerhub)\n│   ├── django (pip)\n│   ├── [aws-ec2-ses (github)] - Manually setup involved\n|   └── acme.sh (github)\n├── aws-ec2-xl2tpd (github)\n│   ├── openswan (yum)\n│   └── xl2tpd (yum)\n└── chap-manager (github)\n```\n\n## Insight\n\n### stack.json\n\nThis repo contains a standard AWS CloudFormation template `stack.json`\nwhich can be deployed with AWS web console, AWS CLI, or any other AWS\nCloudFormation compatible tool.\n\nThis template will create an AWS CloudFormation stack, including\nfollowing resources:\n\n* 1 EC2 Instance.\n    * Shadowsocks-libev is installed if set `EnableSSN=1`.\n        * v2ray-plugin is installed if set `SSV2Ray=1`.\n    * shadowsocks-manager is installed if set `EnableSSM=1`.\n    * L2TPD is installed if set `EnableL2TP=1`.\n\n    For the input parameters and the detail of the template, please check the template\nfile [stack.json](https://github.com/alexzhangs/aws-cfn-vpn).\n\n* 1 nested VPC stack.\n\n    For the details check [aws-cfn-vpc](https://github.com/alexzhangs/aws-cfn-vpc).\n\n* 1 nested VPC peer acceptor stack if set `EnableVpcPeerAcceptor=1`.\n\n    It accepts the VPC peer connection request from another VPC. The VPC peer connection is used to create a private network connection between the manager stack and node stack, to protect the multi-user API from opening to the public internet.\n\n    For the details check\n    [aws-cfn-vpc-peer-acceptor](https://github.com/alexzhangs/aws-cfn-vpc-peer-acceptor).\n\n* 1 nested VPC peer requester stack if set `EnableVpcPeerRequester=1`.\n\n    It sends a request to the acceptor to create a VPC peer connection.\n\n    For the details check\n    [aws-cfn-vpc-peer-requester](https://github.com/alexzhangs/aws-cfn-vpc-peer-requester).\n\n* 1 nested Config service stack if set `EnableConfigProvider=1`.\n\n    It setup Config service, to send the config events to the manager\n    stack so that the EC2 instances and EIP can be registered automatically.\n\n    The following chart shows how it works.\n\n    | Manager\u0026Node Stacks           | Manager Stack                   |\n    |-------------------------------|---------------------------------|\n    | Config events → S3 bucket →   | → SNS -\u003e Lambda → SSM REST APIs |\n\n    For the details check\n    [aws-cfn-config-provider](https://github.com/alexzhangs/aws-cfn-config-provider).\n\n* 1 Lex chat bot if set `EnableLexBot=1`.\n\n    The chatbot is used to manage the node stacks.\n\n    The following chart shows the deployment topology and the control flow.\n\n    | 3rd Part Apps                 | Manager Stack        | Node Stacks                           |\n    |-------------------------------|----------------------|---------------------------------------|\n    | Facebook, Slack, ... → text → | → Lex bot → Lambda → | → SNS → Lambda → CloudFormation → EIP |\n\n    For the details check\n    [aws-cfn-vpn-lexbot](https://github.com/alexzhangs/aws-cfn-vpn-lexbot).\n\n### sample-*.conf\n\n`sample-*.conf` are config files used by `aws/cfn/vpn/deploy` to automate AWS CloudFormation template deployment.\n\n\u003e `aws/cfn/vpn/deploy` can be installed from repo [xsh-lib/aws](https://github.com/xsh-lib/aws).\n\n## Classic Deployment Scenarios\n\nThere are 2 classic deployment scenarios:\n\n1. Deploy a single stack with everything inside, including\nshadowsocks-manager, Shadowsocks node, and L2TPD. This method is not\nrecommended, the shadowsocks-manager will be unreachable once the\nnode's network goes wrong.\nThere's 1 sample config file for this.\n\n    * sample-00-sb.conf\n\n1. Deploy at least 2 stacks, one for shadowsocks-manager and L2TPD,\none or more for Shadowsocks nodes. Each one needs to be deployed in a\ndifferent AWS account. That allows you to balance network traffic between AWS accounts.\nThere are 3 sample config files for this.\n\n    * sample-0-sb.conf\n    * sample-1-sb.conf\n    * sample-2-sb.conf\n\n## Domain Name Design\n\nThere are 3 DNS hostnames needed for your services:\n\n1. The domain name pointing to shadowsocks-manager service, such\nas `admin.ss.example.com`.\n\n1. The domain name pointing to L2TPD services, such as\n`vpn.example.com`.\n\n1. The domain name pointing to Shadowsocks nodes, such as\n`ss.example.com`, or `v2ray.ss.example.com` for v2ray plugin enabled nodes.\n\n## Deploy\n\nThe sample deployment is deploying 3 stacks, one for shadowsocks-manager and L2TPD, two for\nShadowsocks nodes.\n\n### Prepare at local\n\nSeveral tools are needed in the deployment, below shows how to get\nthem ready.\n\n1. awscli: Install it from [here](https://aws.amazon.com/cli/).\n\n1. [xsh](https://github.com/alexzhangs/xsh): xsh is a bash library framework.\n\n    ```bash\n    $ git clone https://github.com/alexzhangs/xsh\n    $ bash xsh/install.sh\n    ```\n\n1. [xsh-lib/core](https://github.com/xsh-lib/core) and [xsh-lib/aws](https://github.com/xsh-lib/aws)\n\n    ```bash\n    $ xsh load xsh-lib/core\n    $ xsh load xsh-lib/aws\n    ```\n\nNote: If you are proceeding without the tools, then you will have to manually\nedit config files and upload templates and Lambda functions to S3, and handle\nthe parameters for each nested template, which is most people want to avoid.\n\n### Prepare AWS Accounts\n\n1. Sign up [AWS accounts](https://aws.amanzon.com) if you don't have one.\n\n    You will need more than one account if planning to deploy multi-node stacks.\n\n1. Create an IAM user and give it admin permissions in each AWS account.\n\n    This can be done with AWS CLI if you already have the access key\n    configured for the account:\n\n    ```sh\n    $ aws iam create-user --user-name admin\n    $ aws iam attach-user-policy --user-name admin --policy-arn \"arn:aws:iam::aws:policy/AdministratorAccess\"\n    ```\n\n    Otherwise, just use the AWS web console.\n\n    NOTE: You must create an [AWS IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)\n    or role to deploy the stacks, you can not use\n    [AWS root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html)\n    or its access key to do the deployment. Because there is IAM assume role inside the template,\n    which assumes an action `ec2:AcceptVpcPeeringConnection` and AWS restricts it's can't be assumed\n    by the root user.\n\n1. Create an access key for each IAM user created in the last step.\n\n    This can be done with AWS CLI if you already have the access key\n    configured for the account:\n\n    ```sh\n    $ aws iam create-access-key --user-name admin\n    ```\n\n    Otherwise, just use the AWS web console.\n\n1. Create a profile for each access key created in the last step.\n\n    Following commands will create three profiles with names:\n    `vpn-0`, `vpn-1`, and `vpn-2` which will be used in\n    the rest of this document.\n\n    A region is needed to be set in this step.\n\n    ```sh\n    $ aws configure --profile=vpn-0\n    $ aws configure --profile=vpn-1\n    $ aws configure --profile=vpn-2\n    ```\n\n### Get the code\n\nIn the same directory:\n\n```sh\n$ git clone https://github.com/alexzhangs/aws-cfn-vpn\n$ git clone https://github.com/alexzhangs/aws-cfn-vpc\n$ git clone https://github.com/alexzhangs/aws-cfn-vpc-peer-acceptor\n$ git clone https://github.com/alexzhangs/aws-cfn-vpc-peer-requester\n$ git clone https://github.com/alexzhangs/aws-cfn-config-provider\n$ git clone https://github.com/alexzhangs/aws-cfn-vpn-lexbot\n```\n\n### Create the manager stack and the node stacks\n\n#### Simplest Way\n\nThe simplest way to create the stacks is to use the high-level wrapper command `aws/cfn/vpn/cluster` provided by the `xsh-lib/aws` library.\n\n```bash\n# Set the environment variables\nXACVC_BASE_DOMAIN=example.com  # replace with your domain\nXACVC_XACC_OPTIONS_DomainNameServerEnv='PROVIDER={dns_provider},LEXICON_PROVIDER_NAME={dns_provider},LEXICON_{DNS_PROVIDER}_{OPTION}={value}[,...]'  # replace with your DNS provider and credentials, see `xsh help -s Environment aws/cfn/vpn/config`\n# example:\nXACVC_XACC_OPTIONS_DomainNameServerEnv='PROVIDER=namecom,LEXICON_PROVIDER_NAME=namecom,LEXICON_NAMECOM_AUTH_USERNAME=your_username,LEXICON_NAMECOM_AUTH_TOKEN=your_token'\n# XACVC_XACC_OPTIONS_SSV2Ray=1  # uncomment this if want to enable v2ray-plugin\n\n# Create the config files and deploy the stacks at once\nxsh aws/cfn/vpn/cluster -x 0-2 -c vpn -C aws-cfn-vpn\n```\n\nThe options listed above is the best practice for the deployment. It minimizes the manual work and the risk of errors, also provides the best security.\n\n`XACVC_XACC_OPTIONS_DomainNameServerEnv` defines the DNS provider and API credentials. It's used to create and update the DNS records for the domains of the web console, L2TP, and Shadowsocks nodes. The TLS certificate (for web console) provision process also depends on it to be fully automated.\n\n| Project                 | Component                  | DNS Library             | Usage                     | Purpose              | Impacted Domain                     | Impacted Feature |\n|-------------------------|----------------------------|-------------------------|---------------------------|----------------------|-------------------------------------|------------------|\n| shadowsocks-manager     | docker-entrypoint.sh       | acme.sh =\u003e dns-lexicon  | domain owner verification | issuing certificates | SSMDomain                           | Nginx HTTPS      |\n| shadowsocks-manager     | domain/models.py           | dns-lexicon             | DNS record management     | DNS record sync      | SSMDomain\u003cbr\u003eL2TPDomain\u003cbr\u003eSSDomain | DNS record sync  |\n| shadowsocks-libev-v2ray | docker-entrypoint.sh       | acme.sh =\u003e dns-lexicon  | domain owner verification | issuing certificates | SSMDomain                           | v2ray-plugin     |\n\nThe command takes around 30 minutes to complete. If everything goes smoothly, you will get 1 manager stack with the L2TPD enabled, and 2 Shadowsocks node stacks with traffic balanced by DNS. You will be able to log in to your manager stack web console with the domain name without any additional setting. \n\n3 config files are created in the directory `aws-cfn-vpn` along with the deployment:\n\n* vpn-0-sb.conf\n* vpn-1-sb.conf\n* vpn-2-sb.conf\n\n#### The Way without API Credentials\n\n```bash\n# Set the environment variables\nXACVC_BASE_DOMAIN=example.com  # replace with your domain\n\n# Create the config files and deploy the stacks at once\nxsh aws/cfn/vpn/cluster -x 0-2 -c vpn -C aws-cfn-vpn\n```\n\nIf the domain is enabled without API credentials, you need to\nmanually create a DNS record to validate the newly created ACM\ncertificate. Visit\n[AWS ACM service](https://console.aws.amazon.com/acm)\nconsole for the manager stack AWS account, to obtain the DNS record info. Once the ACM certificate is validated successfully, the creation will proceed.\n\n#### The Way without Domain\n\n```bash\n# Create the config files and deploy the stacks at once\nxsh aws/cfn/vpn/cluster -x 0-2 -c vpn -C aws-cfn-vpn\n\n# See the help document of the command for the details\nxsh help aws/cfn/vpn/cluster\n```\n\nIf the domain is not enabled at all, the manager stack web console is not HTTPS secured. Therefore, the user and password of web console are sent in plain text. The L2TPD service and the Shadowsocks nodes are not accessible with a domain name, only with the public IP of the EC2 instance.\n\n### Verify the manager stack deployment.\n\nOpen your browser, visit `http://\u003cPUBLIC_IP\u003e/admin`, a login screen should show up.\n\nOr visit `https://admin.ss.example.com/admin`. Note that you\nmust use the HTTPS protocol with using the domain, the HTTP protocol\nwon't work with it.\n\nLog in with the default username and password defined within `vpn-0-sb.conf`:\n\n```ini\n\"SSMAdminUsername=admin\"\n\"SSMAdminPassword=passw0rd\"\n```\n\n## Maintain DNS Records\n\nIf the DNS service API is enabled, then you can skip the following steps,\nshadowsocks-manager should have taken care of the DNS records.\n\nIf you are not in the case above, proceed with the following steps:\n\n1. Create a DNS `A record`, such as `admin.ss`.example.com,\npointing to the public IP address of the EC2 instance of the manager stack.\n\n    Use this domain to access the shadowsocks-manager.\n\n1. Create a DNS `A record`, such as `vpn`.example.com,\npointing to the public IP address of the EC2 instance of the manager stack.\n\n    Use this domain to access the L2TP service.\n\n1. Create a DNS `A record`, such as `ss`.example.com,\npointing to the public IP address of the EC2 Instance of node stack.\n\n    Use this domain to access the Shadowsocks service.\n\n## Configure shadowsocks-manager\n\n1. Log in to the shadowsocks-manager web console at\n`https://admin.ss.example.com/admin` after the DNS records get\neffective.\n\n1. Go to `Home › Shadowsocks › Shadowsocks Nodes`, to check the node\nlist, all node stacks you created should have been registered as nodes\nautomatically.\n\n    Note: The registration relies on the AWS Config, SNS, and Lambda services,\nit takes up to around 5 minutes to capture and deliver the config changes.\n\n1. Now you are ready to create Shadowsocks accounts on the web\n   console, or import the previously exported accounts back.\n\n## Verify L2TPD services\n\nUse your L2TPD client to connect to the service.\n\nWith macOS High Sierra, you can choose the built-in L2TPD client:\n\n```ini\nInterface: VPN\nVPN Type: L2TP over IPSec\n```\n\nThe default credential defined within `vpn-0-sb.conf` is:\n\n```ini\n\"L2TPUsername=vpnuser\"\n\"L2TPPassword=passw0rd\"\n\"L2TPSharedKey=SharedSecret\"\n```\n\n## v2ray-plugin\n\n[v2ray-plugin](https://github.com/shadowsocks/v2ray-plugin) is optionally supported for the Shadowsocks nodes in Websocket (HTTPS) mode.\n\nThe corresponding client settings are:\n\n```ini\nplugin: v2ray-plugin\nplugin_opts: tls;host=v2ray.ss.example.com\n```\n\n\u003e NOTE: The v2ray-plugin is set on node level, all accounts creating on this node are going to be v2ray enabled.\n\n## Customize the Deployment\n\nThe deployment can be customized by:\n\n* setting the environment variables.\n* editing the config files.\n* editing config templates at `aws-cfn-vpn/config-templates` before to generate config files.\n* using the low-level wrapper command `aws/cfn/vpn/config` and `aws/cfn/vpn/deploy` provided by the `xsh-lib/aws` library.\n* editing the stack template `aws-cfn-vpn/stack.json`.\n\nSee help document of the commands for the details.\n\n```bash\nxsh list aws/cfn/vpn\nxsh help aws/cfn/vpn/config\nxsh help aws/cfn/vpn/deploy\n```\n\n## Tips\n\n1. How to change the IP address of the EC2 instance of the Manager stack\n   or the Node stack?\n\n    Update the stack with a new value of parameter `EipDomain`, switch the\nthe value between `vpc` and an empty string ``, this will change the EIP\nof the EC2 instance.\n\n    DO NOT operate on the EIP directly, such as allocate a new EIP\nand associate it, then release the old. This will cause an error\nin locating the original EIP resource when operating on the stack\nlevel.\n\n    For the EC2 instance of the Node stacks, the following methods are recommended:\n\n    * Use the admin web console at `Home › Shadowsocks › Shadowsocks Nodes`.\n    * Use the Lex chatbot.\n\n1. How to enable the HTTPS(SSL certificate) for the Manager stack?\n\n    HTTPS will be enabled by default if you specify a domain for the\n    template parameter `SSMDomain`.\n\n    The TLS certificate is issued for the domain `SSMDomain` with AWS\n    ACM service, the service is free, there's no charge for the certificates.\n\n## Development\n\n### Setup Development Environment\n\n### Re-generate the sample config files\n\n```bash\n# use subshell\n(\n    # Unset the environment variables if they are set, otherwise the command will use the values in the environment.\n    unset $(declare -p | grep ^XACVC | awk -F= '{print $1}')\n    declare -p | grep ^XACVC\n\n    # Generate the sample config file(s): sample-00-sb.conf\n    xsh aws/cfn/vpn/config -x 00 -p vpn-00 -b sample -e sb\n\n    # Generate the sample config file(s): sample-0-sb.conf, sample-1-sb.conf, sample-2-sb.conf\n    xsh aws/cfn/vpn/config -x 0-2 -p vpn-{0..2} -b sample -e sb\n)\n```\n\n### Create the Lambda Layer Packages\n\n1. requests\n\n    ```bash\n    cd lambdas/layers\n    mkdir -p python\n    pip install requests -t python\n    # find and delete all .pyc files and __pycache__ directories\n    find python -name '__pycache__' -type d -exec rm -r {} +\n    find python -name '*.pyc' -type f -delete\n    zip -r9 LambdaLayerRequests.zip python\n    rm -rf python\n    ```\n1. tldextract (no longer required)\n\n    ```bash\n    cd lambdas/layers\n    mkdir -p python\n    pip install tldextract -t python\n    # find and delete all .pyc files and __pycache__ directories\n    find python -name '__pycache__' -type d -exec rm -r {} +\n    find python -name '*.pyc' -type f -delete\n    zip -r9 LambdaLayerTldExtract.zip python\n    rm -rf python\n    ```\n\n* https://www.keyq.cloud/en/blog/creating-an-aws-lambda-layer-for-python-requests-module\n* https://aws.amazon.com/blogs/compute/upcoming-changes-to-the-python-sdk-in-aws-lambda/\n\n\n## TODO\n\n* Add a default Shadowsocks user like the default user for L2TPD.\n\n## Troubleshooting\n\n1. The stack ends up at 'CREATE_FAILED' status.\n\n    Log in to the AWS web console, go to CloudFormation, check the event\n    list of the stack, found the failed events to locate the root reason,\n    check the event list of the nested stack if necessary.\n\n1. For any problem related to the repos that aws-cfn-vpn depends\non, check with the depended repos, here is the quick dial of star\ngates.\n\n   1. [aws-cfn-vpc](https://github.com/alexzhangs/aws-cfn-vpc)\n   1. [aws-cfn-vpc-peer-acceptor](https://github.com/alexzhangs/aws-cfn-vpc-peer-acceptor)\n   1. [aws-cfn-vpc-peer-requester](https://github.com/alexzhangs/aws-cfn-vpc-peer-requester)\n   1. [aws-cfn-config-provider](https://github.com/alexzhangs/aws-cfn-config-provider)\n   1. [aws-cfn-vpn-lexbot](https://github.com/alexzhangs/aws-cfn-vpn-lexbot)\n   1. ~~[aws-cfn-acm](https://github.com/alexzhangs/aws-cfn-acm)~~\n   1. ~~[aws-ec2-shadowsocks-libev](https://github.com/alexzhangs/aws-ec2-shadowsocks-libev)~~\n   1. [shadowsocks-libev-v2ray](https://github.com/alexzhangs/shadowsocks-libev-v2ray)\n   1. [shadowsocks-manager](https://github.com/alexzhangs/shadowsocks-manager)\n   1. [aws-ec2-ses](https://github.com/alexzhangs/aws-ec2-ses)\n   1. [aws-ec2-xl2tpd](https://github.com/alexzhangs/aws-ec2-xl2tpd)\n   1. [chap-manager](https://github.com/alexzhangs/chap-manager)\n\n1. Failed to delete the manager stack.\n\n   If VPC peer connections exist in the manager stacks, deleting the stacks will fail.\n\n   Solution:\n\n   1. Delete all the node stacks before deleting the manager stack.\n\n   2. Manually delete all existing peer connections belong to that stack first. This can be done with AWS web console, or the CLI:\n\n        ```sh\n        $ aws ec2 describe-vpc-peering-connections\n        $ aws ec2 delete-vpc-peering-connection --vpc-peering-connection-id \u003cpeering-connection-id\u003e\n        ```\n\n1. Encountering errors while executing EC2 userdata.\n\n   This might be caused by using the untested AWS AMI.\n   The EC2 userdata is tested only with the following AMIs:\n\n   * Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type\n   * Amazon Linux 2 AMI (HVM), SSD Volume Type - This AMI is\n     **RECOMMENDED** for `aws-cfn-vpn`\n\n   Feel free to open pull requests for the verified compatible AMIs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexzhangs%2Faws-cfn-vpn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexzhangs%2Faws-cfn-vpn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexzhangs%2Faws-cfn-vpn/lists"}