mirror of
https://github.com/WhatsApp/proxy.git
synced 2026-04-22 19:34:35 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# ct needs history to compare
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build the Docker image
|
||||
run: docker build ./proxy/ --tag whatsapp_proxy:$(date +%s)
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v3
|
||||
with:
|
||||
version: v3.10.0
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
check-latest: true
|
||||
|
||||
- name: Helm - Set up chart-testing
|
||||
uses: helm/chart-testing-action@v2.3.1
|
||||
|
||||
- name: Helm - Run chart-testing (list-changed)
|
||||
id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }})
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
|
||||
- name: Helm - Run chart-testing (lint)
|
||||
run: ct lint --target-branch ${{ github.event.repository.default_branch }}
|
||||
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
# The :11 strips the first 11 characters from the environment variable GITHUB_REF which contains refs/tags/v1.2.3 so it yields 1.2.3
|
||||
- name: Set release version (i.e. tag)
|
||||
id: vars
|
||||
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/v}
|
||||
|
||||
- name: Print the release version (i.e. tag)
|
||||
run: echo "TAG = ${{ steps.vars.outputs.tag }}"
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: ./proxy
|
||||
push: true
|
||||
tags: seanlawlor/whatsapp_proxy:${{ steps.vars.outputs.tag }}
|
||||
@@ -0,0 +1,2 @@
|
||||
tmp/
|
||||
helm/whatsapp-proxy-chart*.tgz
|
||||
@@ -0,0 +1,80 @@
|
||||
<!-- Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
License found in the LICENSE file in the root directory
|
||||
of this source tree. -->
|
||||
# Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to make participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, 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 within all project spaces, and it also applies when
|
||||
an individual is representing the project or its community in public spaces.
|
||||
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 team at <opensource-conduct@fb.com>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team 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 https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
@@ -0,0 +1,34 @@
|
||||
<!-- Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
License found in the LICENSE file in the root directory
|
||||
of this source tree. -->
|
||||
# Contributing to this library
|
||||
We want to make contributing to this project as easy and transparent as
|
||||
possible.
|
||||
|
||||
## Pull Requests
|
||||
We actively welcome your pull requests.
|
||||
|
||||
1. Fork the repo and create your branch from `main`.
|
||||
2. If you've added code that should be tested, add tests.
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes.
|
||||
5. If you haven't already, complete the Contributor License Agreement ("CLA").
|
||||
|
||||
## Contributor License Agreement ("CLA")
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need
|
||||
to do this once to work on any of Facebook's open source projects.
|
||||
|
||||
Complete your CLA here: <https://code.facebook.com/cla>
|
||||
|
||||
## Issues
|
||||
We use GitHub issues to track public bugs. Please ensure your description is
|
||||
clear and has sufficient instructions to be able to reproduce the issue.
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
|
||||
disclosure of security bugs. In those cases, please go through the process
|
||||
outlined on that page and do not file a public issue.
|
||||
|
||||
## License
|
||||
By contributing to akd, you agree that your contributions will be
|
||||
licensed under the LICENSE file in the root directory of this source tree.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,137 @@
|
||||
<!-- Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
License found in the LICENSE file in the root directory
|
||||
of this source tree. -->
|
||||
# WhatsApp Chat Proxy
|
||||
|
||||
[<img alt="github" src="https://img.shields.io/badge/github-WhatsApp/proxy-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/WhatsApp/proxy)
|
||||
[<img alt="build status" src="https://img.shields.io/github/workflow/status/WhatsApp/proxy/ci/main?style=for-the-badge" height="20">](https://github.com/WhatsApp/proxy/actions?query=branch%3Amain)
|
||||
|
||||
This project aims to provide an open-proxy implementation based on [HAProxy](https://www.haproxy.org/) which allows users to proxy their mobile apps through a central hub in the event they are unable to contact WhatsApp directly.
|
||||
|
||||
**Current Version**: 1.0
|
||||
## Setup and Installation
|
||||
|
||||
This section outlines a basic setup and configuration for the proxy container which supports upwards of 27K connections concurrently.
|
||||
|
||||
### Dependencies
|
||||
|
||||
1. [Docker](https://docs.docker.com/engine/install/)
|
||||
2. [optional] [Docker compose](https://docs.docker.com/compose/)
|
||||
3. [optional] Enable docker on startup (host system dependent)
|
||||
|
||||
If your version of docker doesn't come pre-installed with Docker compose, you can install a one-off version with (for Linux)
|
||||
|
||||
```bash
|
||||
# Download the pkg
|
||||
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/bin/docker-compose
|
||||
# Enable execution of the script
|
||||
sudo chmod +x /usr/bin/docker-compose
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
You can build the proxy host container with
|
||||
|
||||
```bash
|
||||
docker build /path/to/git/repo/ -t whatsapp_proxy:1.0
|
||||
```
|
||||
|
||||
which will compile the container and tag it as `whatsapp_proxy:1.0` for easy reference.
|
||||
|
||||
### Running
|
||||
|
||||
You can manually execute the docker container with the following docker command
|
||||
|
||||
```bash
|
||||
docker run -it -p 80:80 -p 443:443 -p 5222:5222 -p 8080:8080 -p 8443:8443 -p 8222:8222 -p 8199:8199 whatsapp_proxy:1.0
|
||||
```
|
||||
|
||||
however normally you don't want to manually run the container except for testing scenarios. Therefore we recommend utilizing Docker compose which
|
||||
is a helpful automation tool to manage setting up the container and necessary port forwards, etc without user interaction.
|
||||
|
||||
#### Automate the container lifecycle with Docker Compose
|
||||
|
||||
Docker compose is a tool to run multi-container deployments, but also helps automate the command-line arguments necessary to run a single container. It is a YAML definition file which denotes all of the settings to startup and run the container as well as restart strategies in the event the container crashes or self-restarts.
|
||||
|
||||
We provide a sample [docker-compose.yml](./proxy/ops/docker-compose.yml) file for you which defines a standard deployment of the proxy container. Once docker compose is installed, you can test your specific configuration by running docker compose interactively with
|
||||
|
||||
```bash
|
||||
docker compose -f /path/to/this/repo/docker-compose.yml up
|
||||
```
|
||||
|
||||
which will allow you to see the output from the build + container hosting process to identify if everything is setup correctly. When you are ready to run the container as a service, do
|
||||
|
||||
```bash
|
||||
docker compose -f /path/to/this/repo/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
Note the `-d` flag which means "daemonize" and run as a service. To stop the container you can similarly do
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
Once you have a docker compose setup, you can also automate the deployment for host reboots by utilizing a `systemd` service (if your hosting environment supports it). We provide a sample [`docker_boot.service`](./proxy/ops/docker_boot.service) service definition for you which you should customize to your own environment. To install and setup the `systemd` service you can do the following
|
||||
|
||||
```bash
|
||||
# Copy the service definition to systemd folder
|
||||
cp -v docker_boot.service /etc/systemd/system/
|
||||
# Enable starting the service on startup
|
||||
systemctl enable docker_boot.service
|
||||
# Start the service (will docker compose up the container)
|
||||
systemctl start docker_boot.service
|
||||
# Check container status with
|
||||
docker ps
|
||||
```
|
||||
|
||||
**NOTE:** Make sure to update the path to your specific `docker-compose.yml` file in the service definition `docker_boot.service`!
|
||||
|
||||
## Kubernetes deployment
|
||||
|
||||
See [Helm chart README](./charts/README.md)
|
||||
|
||||
# Architecture Overview
|
||||
|
||||
The provided proxy container exposes multiple ports depending on scenarios you may with to utilize for proxying. The basic ports are
|
||||
|
||||
1. 80: Standard web traffic (HTTP)
|
||||
2. 443: Standard web traffic, encrypted (HTTPS)
|
||||
3. 5222: Jabber protocol traffic (WhatsApp default)
|
||||
|
||||
There are also ports configured which accept incoming [proxy headers](https://www.haproxy.com/blog/use-the-proxy-protocol-to-preserve-a-clients-ip-address/) (version 1 or 2)
|
||||
on connections, such that if you have some kind of network load balancer or something you can preserve the client ip address should you wish.
|
||||
|
||||
1. 8080: Standard web traffic (HTTP) with PROXY protocol expected
|
||||
2. 8443: Standard web traffic, encrypted (HTTPS) with PROXY protocol expected
|
||||
3. 8222: Jabber protocol traffic (WhatsApp default) with PROXY protocol expected
|
||||
|
||||
Additionally the container exposes a stats port on `:8199` which can be connected to directly with `http://<host-ip>:8199` which you can monitor
|
||||
HAProxy statistics.
|
||||
|
||||
## Certificate generation for SSL encrypted ports
|
||||
|
||||
Ports 443 and 8443 are protected by a self-signed encryption certificate generated at container build time. There are some custom options should you wish to tweak the settings of the generated certificates
|
||||
|
||||
* `SSL_DNS` comma seperate list of alternative hostnames, no default
|
||||
* `SSL_IP` comma seperate list of alternative IPs, no default
|
||||
|
||||
They can be set with commands like
|
||||
|
||||
```bash
|
||||
docker build . --build-arg SSL_DNS=test.example.com
|
||||
```
|
||||
|
||||
# Contributors
|
||||
------------
|
||||
|
||||
The authors of this code are
|
||||
|
||||
* Sean Lawlor ([@slawlor](https://github.com/slawlor)).
|
||||
|
||||
To learn more about contributing to this project, [see this document](https://github.com/whatsapp/proxy/blob/main/CONTRIBUTING.md).
|
||||
|
||||
# License
|
||||
-------
|
||||
|
||||
This project is licensed under [MIT](https://github.com/novifinancial/akd/blob/main/LICENSE-MIT).
|
||||
@@ -0,0 +1,50 @@
|
||||
<!-- Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
License found in the LICENSE file in the root directory
|
||||
of this source tree. -->
|
||||
# WhatsApp Proxy Helm Charts
|
||||
|
||||
This guide outlines how to utilize the [Helm chart](https://helm.sh/) for whatsapp-proxy in order to run the proxy in a [kubernetes](https://kubernetes.io/) cluster.
|
||||
|
||||
**NOTE**: This is quite an advanced topic and requires general knowledge around kubernetes and deployments of containers in distributed infrastructure. A healthy knowledge of kubernetes is required to deploy this.
|
||||
|
||||
[<img alt="github" src="https://img.shields.io/badge/github-WhatsApp/proxy-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/WhatsApp/proxy)
|
||||
[<img alt="build status" src="https://img.shields.io/github/workflow/status/WhatsApp/proxy/ci/main?style=for-the-badge" height="20">](https://github.com/WhatsApp/proxy/actions?query=branch%3Amain)
|
||||
|
||||
## Before you begin
|
||||
|
||||
### Setup a Kubernetes Cluster
|
||||
|
||||
The quickest way to setup a Kubernetes cluster is with [Azure Kubernetes Service](https://azure.microsoft.com/en-us/services/kubernetes-service/), [AWS Elastic Kubernetes Service](https://aws.amazon.com/eks/) or [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/) using their respective quick-start guides.
|
||||
|
||||
For setting up Kubernetes on other cloud platforms or bare-metal servers refer to the Kubernetes [getting started guide](http://kubernetes.io/docs/getting-started-guides/).
|
||||
|
||||
### Install Helm
|
||||
|
||||
Get the latest [Helm release](https://github.com/helm/helm#install).
|
||||
|
||||
### Add Helm chart repo
|
||||
|
||||
Once you have Helm installed, add the repo as follows:
|
||||
|
||||
**TBD**
|
||||
|
||||
<!-- ```console
|
||||
helm repo add whatsapp_proxy https://WhatsApp.github.io/proxy
|
||||
helm repo update
|
||||
``` -->
|
||||
|
||||
WhatsApp Proxy Helm charts can be also found on [ArtifactHub](https://artifacthub.io/packages/search?repo=WhatsApp).
|
||||
|
||||
## Search and install charts
|
||||
|
||||
```console
|
||||
helm search repo WhatsApp/
|
||||
helm install my-release WhatsApp/<chart>
|
||||
```
|
||||
|
||||
**_NOTE_**: For instructions on how to install a chart follow instructions in its `README.md`.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome all contributions. Please refer to [guidelines](../CONTRIBUTING.md) on how to make a contribution.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: whatsapp-proxy-lb-1
|
||||
annotations:
|
||||
service.beta.kubernetes.io/do-loadbalancer-name: "whatsapp-proxy-lb-1"
|
||||
service.beta.kubernetes.io/do-loadbalancer-size-unit: "100"
|
||||
service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "80"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "tcp"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-check-interval-seconds: "30"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-response-timeout-seconds: "5"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-unhealthy-threshold: "2"
|
||||
service.beta.kubernetes.io/do-loadbalancer-healthcheck-healthy-threshold: "5"
|
||||
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector:
|
||||
app: whatsapp-proxy
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
- name: https
|
||||
protocol: TCP
|
||||
port: 443
|
||||
targetPort: 8443
|
||||
- name: jabber
|
||||
protocol: TCP
|
||||
port: 5222
|
||||
targetPort: 8222
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.5 KiB |
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
apiVersion: v2
|
||||
name: whatsapp-proxy-chart
|
||||
description: A Helm chart for Kubernetes for the WhatsApp Proxy infrastructure
|
||||
icon: https://github.com/whatsapp/proxy/blob/main/helm/wa_logo.svc
|
||||
maintainers:
|
||||
- name: slawlor
|
||||
email: seanlawlor@meta.com
|
||||
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 1.0.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.0"
|
||||
@@ -0,0 +1,22 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "whatsapp-proxy-chart.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "whatsapp-proxy-chart.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "whatsapp-proxy-chart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "whatsapp-proxy-chart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
{{- end }}
|
||||
@@ -0,0 +1,69 @@
|
||||
{{/*
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
License found in the LICENSE file in the root directory
|
||||
of this source tree.
|
||||
*/}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.labels" -}}
|
||||
helm.sh/chart: {{ include "whatsapp-proxy-chart.chart" . }}
|
||||
{{ include "whatsapp-proxy-chart.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "whatsapp-proxy-chart.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "whatsapp-proxy-chart.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "whatsapp-proxy-chart.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,98 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "whatsapp-proxy-chart.fullname" . }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "whatsapp-proxy-chart.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
{{- if .Values.service.http_proxy_port }}
|
||||
- name: http-proxy
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.http_port }}
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.https_proxy_port }}
|
||||
- name: https-proxy
|
||||
containerPort: 8443
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.https_port }}
|
||||
- name: https
|
||||
containerPort: 443
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.jabber_proxy_port }}
|
||||
- name: jabber-proxy
|
||||
containerPort: 8222
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.jabber_port }}
|
||||
- name: jabber
|
||||
containerPort: 5222
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
{{- if .Values.service.stats_port }}
|
||||
- name: stats
|
||||
containerPort: 8199
|
||||
protocol: TCP
|
||||
{{- end}}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /usr/local/bin/healthcheck.sh
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
env:
|
||||
- name: "PUBLIC_IP"
|
||||
value: "{{ .Values.public_ip }}"
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "whatsapp-proxy-chart.fullname" . }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "whatsapp-proxy-chart.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "whatsapp-proxy-chart.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,58 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "whatsapp-proxy-chart.fullname" . }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
{{- if .Values.service.http_proxy_port }}
|
||||
- port: {{ .Values.service.http_proxy_port }}
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http-proxy
|
||||
{{- end}}
|
||||
{{- if .Values.service.https_proxy_port }}
|
||||
- port: {{ .Values.service.https_proxy_port }}
|
||||
targetPort: 8443
|
||||
protocol: TCP
|
||||
name: https-proxy
|
||||
{{- end}}
|
||||
{{- if .Values.service.jabber_proxy_port }}
|
||||
- port: {{ .Values.service.jabber_proxy_port }}
|
||||
targetPort: 8222
|
||||
protocol: TCP
|
||||
name: jabber-proxy
|
||||
{{- end}}
|
||||
{{- if .Values.service.jabber_port }}
|
||||
- port: {{ .Values.service.jabber_port }}
|
||||
targetPort: 5222
|
||||
protocol: TCP
|
||||
name: jabber
|
||||
{{- end}}
|
||||
{{- if .Values.service.http_port }}
|
||||
- port: {{ .Values.service.http_port }}
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- end}}
|
||||
{{- if .Values.service.https_port }}
|
||||
- port: {{ .Values.service.https_port }}
|
||||
targetPort: 443
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- end}}
|
||||
{{- if .Values.service.stats_port }}
|
||||
- port: {{ .Values.service.stats_port }}
|
||||
targetPort: {{ .Values.service.stats_port }}
|
||||
protocol: TCP
|
||||
name: stats
|
||||
{{- end}}
|
||||
selector:
|
||||
{{- include "whatsapp-proxy-chart.selectorLabels" . | nindent 4 }}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "whatsapp-proxy-chart.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "whatsapp-proxy-chart.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "whatsapp-proxy-chart.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "whatsapp-proxy-chart.fullname" . }}:{{ .Values.service.stats_port }}']
|
||||
restartPolicy: Never
|
||||
@@ -0,0 +1,95 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
# Default values for whatsapp-proxy-chart.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 10
|
||||
|
||||
image:
|
||||
repository: seanlawlor/whatsapp_proxy
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: "1.0"
|
||||
|
||||
public_ip: "10.0.0.1"
|
||||
|
||||
imagePullSecrets: {}
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: "whatsapp-proxy"
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
# http_port: 80
|
||||
# https_port: 443
|
||||
# jabber_port: 5222
|
||||
http_proxy_port: 8080
|
||||
https_proxy_port: 8443
|
||||
jabber_proxy_port: 8222
|
||||
# stats_port: 8199
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: waprox.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
ops/
|
||||
@@ -0,0 +1,56 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
FROM haproxy:lts-alpine
|
||||
|
||||
# Install dependencies for healthcheck support
|
||||
USER root
|
||||
RUN apk --update --no-cache add curl openssl jq bash
|
||||
|
||||
# Customization variables for certificate generation
|
||||
ARG SSL_IP
|
||||
ARG SSL_DNS
|
||||
|
||||
# Generate + copy the self-signed certificate settings
|
||||
WORKDIR /certs
|
||||
COPY src/generate-certs.sh /usr/local/bin/generate-certs.sh
|
||||
RUN chmod +x /usr/local/bin/generate-certs.sh && \
|
||||
/usr/local/bin/generate-certs.sh && \
|
||||
mkdir --parents /etc/haproxy/ssl/ && \
|
||||
mv /certs/proxy.whatsapp.net.pem /etc/haproxy/ssl/proxy.whatsapp.net.pem && \
|
||||
chown -R haproxy:haproxy /etc/haproxy/
|
||||
WORKDIR /
|
||||
|
||||
# Copy the public-ip setting + sshd startup script
|
||||
COPY --chown=haproxy:haproxy src/set_public_ip_and_start.sh /usr/local/bin/set_public_ip_and_start.sh
|
||||
RUN chmod +x /usr/local/bin/set_public_ip_and_start.sh
|
||||
|
||||
# Copy the HAProxy configuration
|
||||
COPY --chown=haproxy:haproxy src/proxy_config.cfg /usr/local/etc/haproxy/haproxy.cfg
|
||||
RUN chown haproxy:haproxy /usr/local/etc/haproxy
|
||||
|
||||
# Copy + define the healthcheck
|
||||
COPY src/healthcheck.sh /usr/local/bin/healthcheck.sh
|
||||
RUN chmod +x /usr/local/bin/healthcheck.sh
|
||||
HEALTHCHECK --interval=10s --start-period=5s CMD bash /usr/local/bin/healthcheck.sh
|
||||
|
||||
RUN mkdir --parents /home/haproxy/certs && chown haproxy:haproxy /home/haproxy/certs
|
||||
|
||||
# Validate the HAProxy configuration file (sanity check)
|
||||
RUN haproxy -c -V -f /usr/local/etc/haproxy/haproxy.cfg
|
||||
|
||||
# Revert to the haproxy user for runtime operation
|
||||
USER haproxy
|
||||
|
||||
# Expose the container-supported network ports
|
||||
EXPOSE 80/tcp
|
||||
EXPOSE 8080/tcp
|
||||
EXPOSE 443/tcp
|
||||
EXPOSE 8443/tcp
|
||||
EXPOSE 5222/tcp
|
||||
EXPOSE 8222/tcp
|
||||
EXPOSE 8199/tcp
|
||||
|
||||
# This is the startup command which also runs a background job to manage the WAPOX IPs
|
||||
CMD /usr/local/bin/set_public_ip_and_start.sh
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
version: '3.3'
|
||||
|
||||
services:
|
||||
proxy:
|
||||
container_name: whatsapp_proxy
|
||||
build: ../
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80" # HTTP
|
||||
- "443:443" # HTTPS
|
||||
- "5222:5222" # JABBER
|
||||
- "8199:8199" # HAPROXY statistics page
|
||||
- "8080:8080" # HTTP with accept-proxy processing
|
||||
- "8443:8443" # HTTPS with accept-proxy processing
|
||||
- "8222:8222" # JABBER with accept-proxy processing
|
||||
healthcheck:
|
||||
test: /usr/local/bin/healthcheck.sh
|
||||
interval: 10s
|
||||
start_period: 5s
|
||||
environment:
|
||||
- PUBLIC_IP=10.0.0.1
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
## Systemd definition for an example service to startup the proxy container on host reboot
|
||||
|
||||
[Unit]
|
||||
description=docker boot
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
WorkingDirectory=/root/wa
|
||||
ExecStart=docker compose -f /root/whatsapp_proxy/docker-compose.yml up -d
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
echo "----------------------------"
|
||||
echo "| SSL Cert Generator |"
|
||||
echo "----------------------------"
|
||||
echo
|
||||
|
||||
export CA_KEY="ca-key.pem"
|
||||
export CA_CERT="ca.pem"
|
||||
export CA_SUBJECT="whatsapp.selfsigned"
|
||||
export CA_EXPIRE="36500" # 100 years
|
||||
|
||||
export SSL_CONFIG="openssl.cnf"
|
||||
export SSL_KEY="key.pem"
|
||||
export SSL_CSR="key.csr"
|
||||
export SSL_CERT="cert.pem"
|
||||
export SSL_SIZE="2048"
|
||||
export SSL_EXPIRE="3650" # 10 years
|
||||
|
||||
export SSL_SUBJECT="proxy.whatsapp.net"
|
||||
export SSL_DNS=${SSL_DNS}
|
||||
export SSL_IP=${SSL_IP}
|
||||
|
||||
export DEBUG=${DEBUG:=1}
|
||||
|
||||
echo "--> Certificate Authority"
|
||||
|
||||
if [[ -e ./${CA_KEY} ]]; then
|
||||
echo "====> Using existing CA Key ${CA_KEY}"
|
||||
else
|
||||
echo "====> Generating new CA key ${CA_KEY}"
|
||||
openssl genrsa -out ${CA_KEY} 2048
|
||||
fi
|
||||
|
||||
if [[ -e ./${CA_CERT} ]]; then
|
||||
echo "====> Using existing CA Certificate ${CA_CERT}"
|
||||
else
|
||||
echo "====> Generating new CA Certificate ${CA_CERT}"
|
||||
openssl req -x509 -new -nodes -key ${CA_KEY} -days ${CA_EXPIRE} -out ${CA_CERT} -subj "/CN=${CA_SUBJECT}" || exit 1
|
||||
fi
|
||||
|
||||
[[ -n $DEBUG ]] && cat $CA_CERT
|
||||
|
||||
echo "====> Generating new config file ${SSL_CONFIG}"
|
||||
cat > ${SSL_CONFIG} <<EOM
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth, serverAuth
|
||||
EOM
|
||||
|
||||
if [[ -n ${SSL_DNS} || -n ${SSL_IP} ]]; then
|
||||
cat >> ${SSL_CONFIG} <<EOM
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
EOM
|
||||
|
||||
IFS=","
|
||||
dns=(${SSL_DNS})
|
||||
dns+=(${SSL_SUBJECT})
|
||||
for i in "${!dns[@]}"; do
|
||||
echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG}
|
||||
done
|
||||
|
||||
if [[ -n ${SSL_IP} ]]; then
|
||||
ip=(${SSL_IP})
|
||||
for i in "${!ip[@]}"; do
|
||||
echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG}
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "====> Generating new SSL KEY ${SSL_KEY}"
|
||||
openssl genrsa -out ${SSL_KEY} ${SSL_SIZE} || exit 1
|
||||
|
||||
echo "====> Generating new SSL CSR ${SSL_CSR}"
|
||||
openssl req -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/CN=${SSL_SUBJECT}" -config ${SSL_CONFIG} || exit 1
|
||||
|
||||
echo "====> Generating new SSL CERT ${SSL_CERT}"
|
||||
openssl x509 -req -in ${SSL_CSR} -CA ${CA_CERT} -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \
|
||||
-days ${SSL_EXPIRE} -extensions v3_req -extfile ${SSL_CONFIG} || exit 1
|
||||
|
||||
echo "====> Generating SSL CERT / KEY COMBO proxy.whatsapp.net.pem"
|
||||
cat ${SSL_KEY} > proxy.whatsapp.net.pem
|
||||
cat ${SSL_CERT} >> proxy.whatsapp.net.pem
|
||||
|
||||
echo "Certificate generation completed."
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
curl -s -w 2 "http://127.0.0.1:8199/;csv" > /tmp/stats.txt || exit 1
|
||||
|
||||
# First trim off the leading line which is just "#"
|
||||
# Then convert the ugly CSV to slightly less ugly JSON
|
||||
# Filter out the lines for g_whatsapp_net backend status
|
||||
# Select the "check_desc" field (Description of the check result)
|
||||
# and take all results that do NOT equal "Layer4 check passed" from HAProxy
|
||||
RESULT=$(tail -n +1 /tmp/stats.txt | jq -R 'split(",")' | jq -c '. | select(.[1] | contains("g_whatsapp_net"))' | jq --raw-output '.[65]| select(. | test("Layer4 check passed") | not)')
|
||||
|
||||
# # CSV output header row:
|
||||
# # ["# pxname","svname","qcur","qmax","scur","smax","slim","stot","bin","bout","dreq","dresp","ereq","econ","eresp","wretr","wredis","status","weight","act","bck","chkfail","chkdown","lastchg","downtime","qlimit","pid","iid","sid","throttle","lbtot","tracked","type","rate","rate_lim","rate_max","check_status","check_code","check_duration","hrsp_1xx","hrsp_2xx","hrsp_3xx","hrsp_4xx","hrsp_5xx","hrsp_other","hanafail","req_rate","req_rate_max","req_tot","cli_abrt","srv_abrt","comp_in","comp_out","comp_byp","comp_rsp","lastsess","last_chk","last_agt","qtime","ctime","rtime","ttime","agent_status","agent_code","agent_duration","check_desc","agent_desc","check_rise","check_fall","check_health","agent_rise","agent_fall","agent_health","addr","cookie","mode","algo","conn_rate","conn_rate_max","conn_tot","intercepted","dcon","dses","wrew","connect","reuse","cache_lookups","cache_hits","srv_icur","src_ilim","qtime_max","ctime_max","rtime_max","ttime_max","eint","idle_conn_cur","safe_conn_cur","used_conn_cur","need_conn_est","uweight","agg_server_check_status","-","ssl_sess","ssl_reused_sess","ssl_failed_handshake","h2_headers_rcvd","h2_data_rcvd","h2_settings_rcvd","h2_rst_stream_rcvd","h2_goaway_rcvd","h2_detected_conn_protocol_errors","h2_detected_strm_protocol_errors","h2_rst_stream_resp","h2_goaway_resp","h2_open_connections","h2_backend_open_streams","h2_total_connections","h2_backend_total_streams",""]
|
||||
|
||||
if [ "$RESULT" != "" ]
|
||||
then
|
||||
echo "[HEALTHCHECKER] Container failed healthchecks, L4 healthcheck on g.whatsapp.net failed"
|
||||
echo "[HEALTKCHECKER] Result $RESULT"
|
||||
exit -1;
|
||||
fi
|
||||
|
||||
exit 0;
|
||||
@@ -0,0 +1,88 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
## This file contains the HAProxy configuration for the WhatsApp proxy host use-case
|
||||
|
||||
# Documentation
|
||||
# https://cbonte.github.io/haproxy-dconv/2.5/configuration.html#maxconn
|
||||
|
||||
global
|
||||
# Default buffer size is 16kB and we need 2 buffers/conn.
|
||||
# For WA we want a lower memory footprint, so we lower it to 4kB.
|
||||
tune.bufsize 4096
|
||||
|
||||
# We limit the connection count to 27.5K connections concurrently such that
|
||||
# to fail healthchecks we'd have to actually have health problems rather than just reject connections
|
||||
#
|
||||
# Upon the 27501'th connection on a proxy port, it'll be REJECTED in favor of reconnecting to a different proxy host
|
||||
# which will mean the existing connection will be serviced without the host being recycled
|
||||
maxconn 27500
|
||||
|
||||
# Adds some randomness on the interval delay between two consecutive health checks
|
||||
spread-checks 5
|
||||
|
||||
# # Log to local rsyslogd (levels: emerg alert crit err warning notice info debug)
|
||||
# log 127.0.0.1 local0 notice
|
||||
ssl-server-verify none
|
||||
|
||||
# ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
# ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
||||
# ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
# ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
||||
|
||||
|
||||
defaults
|
||||
mode tcp
|
||||
# we don't retain this information for long since connections are load balanced they'll end up on a new host
|
||||
timeout client-fin 1s
|
||||
timeout server-fin 1s
|
||||
timeout connect 5s
|
||||
timeout client 200s
|
||||
timeout server 200s
|
||||
log global
|
||||
option tcplog
|
||||
default-server inter 10s fastinter 1s downinter 3s error-limit 50
|
||||
|
||||
listen stats
|
||||
bind :::8199
|
||||
mode http
|
||||
stats uri /
|
||||
|
||||
# These expect direct connections from clients or through NLB balanced
|
||||
# connections
|
||||
frontend haproxy_v4_http
|
||||
maxconn 27495
|
||||
#PUBLIC_IP
|
||||
|
||||
bind ipv4@*:80
|
||||
bind ipv4@*:8080 accept-proxy
|
||||
|
||||
default_backend wa_http
|
||||
|
||||
frontend haproxy_v4_https
|
||||
maxconn 27495
|
||||
#PUBLIC_IP
|
||||
|
||||
bind ipv4@*:443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem
|
||||
bind ipv4@*:8443 ssl crt /etc/haproxy/ssl/proxy.whatsapp.net.pem accept-proxy
|
||||
|
||||
default_backend wa
|
||||
|
||||
frontend haproxy_v4_xmpp
|
||||
maxconn 27495
|
||||
#PUBLIC_IP
|
||||
|
||||
bind ipv4@*:5222
|
||||
bind ipv4@*:8222 accept-proxy
|
||||
|
||||
default_backend wa
|
||||
|
||||
backend wa
|
||||
default-server check inter 60000 observe layer4 send-proxy
|
||||
server g_whatsapp_net_5222 g.whatsapp.net:5222
|
||||
|
||||
backend wa_http
|
||||
default-server check inter 60000 observe layer4 send-proxy
|
||||
server g_whatsapp_net_80 g.whatsapp.net:80
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# License found in the LICENSE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
## About:
|
||||
# This script replaces instances of #PUBLIC_IP in the HaProxy configuration files
|
||||
# with the the real public ip. There's an order of priority here which is
|
||||
# 1. Environment variable
|
||||
# 2. AWS EC2 Metadata endpoint
|
||||
#
|
||||
# If all fails, we'll just not set the destination IP address
|
||||
|
||||
CONFIG_FILE="/usr/local/etc/haproxy/haproxy.cfg"
|
||||
|
||||
## PUBLIC_IP supplied from environment variable
|
||||
if [[ $PUBLIC_IP == '' ]]
|
||||
then
|
||||
echo "[PROXYHOST] No public IP address was supplied as an environment variable."
|
||||
fi
|
||||
|
||||
## PUBLIC_IP retrieved from AWS EC2 metadata endpoint
|
||||
if [[ $PUBLIC_IP == '' ]]
|
||||
then
|
||||
# Attempt retrieval of the public ip from the meta-data instance
|
||||
PUBLIC_IP=$(curl --max-time 2 -s http://169.254.169.254/latest/meta-data/public-ipv4)
|
||||
if [[ $PUBLIC_IP == '' ]]
|
||||
then
|
||||
echo "[PROXYHOST] Failed to retrieve public ip address from AWS URI within 2s"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now if the public IP is available (test is for not-empty)
|
||||
# then replace the instances in all haproxy config lines
|
||||
if [[ ! -z "$PUBLIC_IP" ]]
|
||||
then
|
||||
echo "[PROXYHOST] Public IP address ($PUBLIC_IP) in-place replacement occurring on $CONFIG_FILE"
|
||||
# Replace all instances of #PUBLIC_IP with the
|
||||
# haproxy configuration statement for the frontend which set's the destination
|
||||
# ip to the public ip of the container (which is necessary to determine our IP's
|
||||
# internally within WA)
|
||||
sed -i "s/#PUBLIC\_IP/tcp-request connection set-dst ipv4($PUBLIC_IP)/g" $CONFIG_FILE
|
||||
fi
|
||||
|
||||
# Setup a new, on-the-fly certificate for the HTTPS port (so this re-generates each restart)
|
||||
pushd /home/haproxy/certs
|
||||
/usr/local/bin/generate-certs.sh
|
||||
mv proxy.whatsapp.net.pem /etc/haproxy/ssl/proxy.whatsapp.net.pem
|
||||
chown haproxy:haproxy /etc/haproxy/ssl/proxy.whatsapp.net.pem
|
||||
popd
|
||||
|
||||
# Start HAProxy
|
||||
haproxy -f "$CONFIG_FILE"
|
||||
Reference in New Issue
Block a user