Skip to content

Commit fe31ae2

Browse files
committed
Added K8S support and guide
1 parent b4cf81a commit fe31ae2

17 files changed

+647
-9
lines changed

README.md

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Dockerized ReactJS, Flask, LDAP-auth boilerplate
1+
# Dockerized ReactJS, Flask, LDAP boilerplate
22

33
<p align="center">
44
<a href="https://travis-ci.org/flavienbwk/reactjs-flask-ldap-boilerplate.svg?branch=master" target="_blank">
@@ -15,11 +15,11 @@
1515
- Docker architecture
1616
- LDAP authentication
1717
- Token-based API authentication
18-
- Automatic [token renewal](./api/app/service/auth_service.py#L44) with [a Flask middleware](./api/app/service/auth_service.py#L31)
18+
- Automatic [token renewal](./api/app/service/auth_service.py#L45) with [a Flask middleware](./api/app/service/auth_service.py#L32)
1919
- Swagger documentation
2020
- Flask-Migrate
2121
- Flask-SQLAlchemy (PostgreSQL was chosen)
22-
- [Logging and logs rotation](./api/app/utils/Logger.py#L12)
22+
- [Logging and logs rotation](./api/app/utils/Logger.py#L11)
2323
- [Choose](./app/app/src/App.js#L65) between sidebar and navbar (or use both !)
2424
- Responsive design
2525
- [Production](./prod.docker-compose.yml) and [development](./docker-compose.yml) builds
@@ -46,7 +46,7 @@ With this boilerplate, you will be able to develop corporate-ready services AND
4646

4747
This section will explain how to properly run this project and set-up the LDAP server with one user.
4848

49-
1. Copy the `.env.example` to `.env`
49+
1. Copy the `.env.example` file to `.env`
5050

5151
```bash
5252
cp .env.example .env
@@ -133,3 +133,47 @@ This section will explain how to properly run this project and set-up the LDAP s
133133
```
134134
135135
Access the UI at `https://localhost:8080`
136+
137+
### Deploy to K8S
138+
139+
I pretend you have here your K8S instance configured to be accessed by your `kubectl` CLI.
140+
141+
I've used [Scaleway Kapsule](https://www.scaleway.com/en/kubernetes-kapsule) to perform my tests. This is an easy way to have a Kubernetes cluster quickly ready.
142+
143+
1. Building production images (optional)
144+
145+
Images are tagged `flavienb/reactjs-flask-ldap-boilerplate-{api,web,nginx}:latest` by default. Edit it in `prod.docker-compose.yml` before building.
146+
147+
:information_source: You might be interested in pushing your images in a private registry (e.g: [Scaleway's Container Registry service](https://www.scaleway.com/en/container-registry/)).
148+
149+
```bash
150+
docker-compose -f prod.docker-compose.yml build
151+
```
152+
153+
Finally, `docker push` the 3 images and edit K8S' configurations :
154+
155+
- [k8s/app.yaml, line 26](k8s/app.yaml#L26)
156+
- [k8s/api.yaml, line 21](k8s/api.yaml#L21)
157+
- [k8s/nginx.yaml, line 21](k8s/nginx.yaml#L21)
158+
159+
2. Add a new `reactjs-flask-ldap-boilerplate` namespace
160+
161+
```bash
162+
kubectl create namespace my-app
163+
```
164+
165+
3. Configure your Ingress app endpoint
166+
167+
- **Edit** the env variables in [k8s/env-configmap.yaml](./k8s/env-configmap.yaml)
168+
- **Edit** the app and phpldapadmin endpoints in [k8s/ingress.yaml, line 10 and 35](./k8s/ingress.yaml#L10)
169+
- **Check** the PersistentVolumeClaim if you're not using Scaleway in all `*-pvc.yaml` files
170+
171+
Deploy with :
172+
173+
```bash
174+
kubectl apply -f ./k8s
175+
```
176+
177+
4. Configure the first user
178+
179+
**Create** your first user by accessing phpLDAPAdmin at [endpoint defined](./k8s/ingress.yaml#L35) and [following the LDAP user creation guide](./CREATE_LDAP_USER.md).

api/app/service/auth_service.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,12 @@ def authLDAPUser(username: str, password: str):
6767
# from users's LDAP details
6868
sql_datetime = datetime.datetime.utcnow()
6969
last_id = (UserService.getLastUserID() + 1)
70+
first_name = user_details[0][1]["givenName"][0].decode('utf-8')\
71+
if "givenName" in user_details[0][1] else "" # givenName is optional in LDAP
7072
UserService.createUser({
7173
"ids": sha256(hash_id(last_id) + str(time.time())),
7274
"username": username,
73-
"first_name": user_details[0][1]["givenName"][0].decode('utf-8'),
75+
"first_name": first_name,
7476
"last_name": user_details[0][1]["sn"][0].decode('utf-8'),
7577
"created_at": sql_datetime,
7678
"updated_at": sql_datetime

api/app/service/user_service.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ def updateLDAPUser(user: User):
6868
ldap_user = connection.search_s(LDAP_USERS_DN, ldap.SCOPE_SUBTREE, search_filter)
6969
if len(ldap_user):
7070
ldap_user_details = {
71-
"first_name": ldap_user[0][1]["givenName"][0].decode('utf-8'),
71+
"first_name": ldap_user[0][1]["givenName"][0].decode('utf-8')\
72+
if "givenName" in ldap_user[0][1] else "", # givenName is optional in LDAP
7273
"last_name": ldap_user[0][1]["sn"][0].decode('utf-8')
7374
}
7475
user_details = {

docker-compose.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ version: "3.3"
22

33
services:
44

5-
65
# LDAP-related
76

87
ldap:

k8s/api-pvc.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: v1
2+
kind: PersistentVolumeClaim
3+
metadata:
4+
namespace: my-app
5+
name: api-logs-pvc
6+
spec:
7+
accessModes:
8+
- ReadWriteOnce
9+
storageClassName: scw-bssd-retain # Specific to Scaleway Kapsule
10+
resources:
11+
requests:
12+
storage: 5Gi
13+
---
14+
apiVersion: v1
15+
kind: PersistentVolumeClaim
16+
metadata:
17+
namespace: my-app
18+
name: api-migrations-pvc
19+
spec:
20+
accessModes:
21+
- ReadWriteOnce
22+
storageClassName: scw-bssd-retain # Specific to Scaleway Kapsule
23+
resources:
24+
requests:
25+
storage: 1Gi

k8s/api.yaml

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
namespace: my-app
5+
labels:
6+
app: api
7+
name: api
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: api
13+
strategy:
14+
type: Recreate
15+
template:
16+
metadata:
17+
labels:
18+
app: api
19+
spec:
20+
containers:
21+
- image: flavienb/reactjs-flask-ldap-boilerplate-api:latest
22+
name: api
23+
ports:
24+
- containerPort: 5000
25+
imagePullPolicy: Always
26+
env:
27+
- name: FLASK_LEVEL
28+
valueFrom:
29+
configMapKeyRef:
30+
key: FLASK_LEVEL
31+
name: env
32+
- name: LOG_LEVEL
33+
valueFrom:
34+
configMapKeyRef:
35+
key: LOG_LEVEL
36+
name: env
37+
- name: FLASK_SERVER_NAME
38+
valueFrom:
39+
configMapKeyRef:
40+
key: FLASK_SERVER_NAME
41+
name: env
42+
- name: FLASK_SERVER_DESCRIPTION
43+
valueFrom:
44+
configMapKeyRef:
45+
key: FLASK_SERVER_DESCRIPTION
46+
name: env
47+
- name: FLASK_SECRET_KEY
48+
valueFrom:
49+
configMapKeyRef:
50+
key: FLASK_SECRET_KEY
51+
name: env
52+
- name: LDAP_HOST
53+
valueFrom:
54+
configMapKeyRef:
55+
key: LDAP_HOST
56+
name: env
57+
- name: LDAP_SCHEME
58+
valueFrom:
59+
configMapKeyRef:
60+
key: LDAP_SCHEME
61+
name: env
62+
- name: LDAP_PORT
63+
valueFrom:
64+
configMapKeyRef:
65+
key: LDAP_PORT
66+
name: env
67+
- name: LDAP_USERS_DN
68+
valueFrom:
69+
configMapKeyRef:
70+
key: LDAP_USERS_DN
71+
name: env
72+
- name: LDAP_ADMIN_DN
73+
valueFrom:
74+
configMapKeyRef:
75+
key: LDAP_ADMIN_DN
76+
name: env
77+
- name: LDAP_ADMIN_PASSWORD
78+
valueFrom:
79+
configMapKeyRef:
80+
key: LDAP_ADMIN_PASSWORD
81+
name: env
82+
- name: POSTGRES_HOST
83+
valueFrom:
84+
configMapKeyRef:
85+
key: POSTGRES_HOST
86+
name: env
87+
- name: POSTGRES_PORT
88+
valueFrom:
89+
configMapKeyRef:
90+
key: POSTGRES_PORT
91+
name: env
92+
- name: POSTGRES_USER
93+
valueFrom:
94+
configMapKeyRef:
95+
key: POSTGRES_USER
96+
name: env
97+
- name: POSTGRES_PASSWORD
98+
valueFrom:
99+
configMapKeyRef:
100+
key: POSTGRES_PASSWORD
101+
name: env
102+
- name: POSTGRES_DB
103+
valueFrom:
104+
configMapKeyRef:
105+
key: POSTGRES_DB
106+
name: env
107+
volumeMounts:
108+
- mountPath: /logs
109+
name: api-logs-pvc
110+
- mountPath: /migrations
111+
subPath: migrations # https://stackoverflow.com/a/51174380/4958081
112+
name: api-migrations-pvc
113+
resources: {}
114+
volumes:
115+
- name: api-logs-pvc
116+
persistentVolumeClaim:
117+
claimName: api-logs-pvc
118+
- name: api-migrations-pvc
119+
persistentVolumeClaim:
120+
claimName: api-migrations-pvc
121+
restartPolicy: Always
122+
status: {}
123+
---
124+
apiVersion: v1
125+
kind: Service
126+
metadata:
127+
labels:
128+
app: api
129+
namespace: my-app
130+
name: api
131+
spec:
132+
ports:
133+
- port: 5000
134+
targetPort: 5000
135+
selector:
136+
app: api
137+
status:
138+
loadBalancer: {}

k8s/app.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
namespace: my-app
5+
labels:
6+
app: app
7+
name: app
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: app
13+
strategy: {}
14+
template:
15+
metadata:
16+
labels:
17+
app: app
18+
spec:
19+
containers:
20+
- env:
21+
- name: NODE_ENV
22+
valueFrom:
23+
configMapKeyRef:
24+
key: NODE_ENV
25+
name: env
26+
- name: CHOKIDAR_USEPOLLING
27+
valueFrom:
28+
configMapKeyRef:
29+
key: CHOKIDAR_USEPOLLING
30+
name: env
31+
image: flavienb/reactjs-flask-ldap-boilerplate-app:latest
32+
name: app
33+
ports:
34+
- containerPort: 3000
35+
imagePullPolicy: Always
36+
resources: {}
37+
restartPolicy: Always
38+
status: {}
39+
---
40+
apiVersion: v1
41+
kind: Service
42+
metadata:
43+
namespace: my-app
44+
labels:
45+
app: app
46+
name: app
47+
spec:
48+
ports:
49+
- port: 3000 # Port accessible inside cluster
50+
targetPort: 3000 # Port to forward to inside the pod
51+
protocol: TCP
52+
name: http
53+
selector:
54+
app: app
55+
status:
56+
loadBalancer: {}

k8s/database-pvc.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v1
2+
kind: PersistentVolumeClaim
3+
metadata:
4+
namespace: my-app
5+
name: database-pvc
6+
spec:
7+
accessModes:
8+
- ReadWriteOnce
9+
storageClassName: scw-bssd-retain # Specific to Scaleway Kapsule
10+
resources:
11+
requests:
12+
storage: 10Gi

0 commit comments

Comments
 (0)