Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8dd75b1

Browse files
perf: cache files with redis to reduce registry load (#3)
* refactor: cleanup dependencies / SSL with @interactivetraining/acme-client * feat: add directory listing (#2) * fix(getPackageFileList): move downloadPackage() call outside promise * feat: add redis to reduce registry load
1 parent 0defad6 commit 8dd75b1

File tree

13 files changed

+276
-210
lines changed

13 files changed

+276
-210
lines changed

‎.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
.gitignore
44
Dockerfile
55
README.md
6-
.env
76
node_modules
87
npm-debug.log
8+
build-for-run.sh

‎.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ dist/
2424
*.pem
2525
acme/
2626
cache/
27+
28+
build-for-run.sh

‎Dockerfile

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
FROM node:10
22

3-
LABEL version="0.0.1"
3+
LABEL version="0.0.2"
44

55
WORKDIR /usr/src/app
66

77
COPY . .
88

99
RUN npm install
1010

11-
EXPOSE 443
12-
EXPOSE 80
13-
14-
VOLUME /usr/src/app/cache
11+
VOLUME /usr/src/app
1512

1613
CMD [ "npm", "run", "start" ]

‎README.md

Lines changed: 11 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,17 @@
11
# self-hosted-unpkg
22

3-
## Run locally
4-
Create .env file. (see sample.env) and run:
3+
## Requirements
4+
- Registry token or credentials (if you want to allow access to private packages)
5+
- Redis (if you want short-term file caching to reduce registry load)
56

6-
```bash
7-
docker run -it --rm -p 443:443 -p 80:80 -v /local/path/to/cache:/usr/src/app/cache --env-file ./.env --name self-hosted-unpkg interactivetraining/self-hosted-unpkg
8-
```
7+
### For HTTPS
8+
- Cloudflare credentials (used to verify domain with Lets Encrypt)
9+
- Google Cloud Storage + service account (for storing SSL cert/key)
910

10-
## Kubernetes Deployment
1111

12-
### Create a secret from your env file
13-
```bash
14-
kubectl create secret generic __MY_SECRET_NAME__ --from-env-file ./path/to/.env
15-
```
12+
## Example
13+
Create .env file. (see http.sample.env) and run:
1614

17-
### Add each variable to your deployment
18-
```yaml
19-
apiVersion: extensions/v1beta1
20-
kind: Deployment
21-
spec:
22-
template:
23-
spec:
24-
containers:
25-
- env:
26-
- name: DOMAIN
27-
valueFrom:
28-
secretKeyRef:
29-
key: DOMAIN
30-
name: __MY_SECRET_NAME__
31-
- name: NPM_REGISTRY
32-
valueFrom:
33-
secretKeyRef:
34-
key: NPM_REGISTRY
35-
name: __MY_SECRET_NAME__
36-
- name: NPM_TOKEN
37-
valueFrom:
38-
secretKeyRef:
39-
key: NPM_TOKEN
40-
name: __MY_SECRET_NAME__
41-
- name: CLOUDFLARE_EMAIL
42-
valueFrom:
43-
secretKeyRef:
44-
key: CLOUDFLARE_EMAIL
45-
name: __MY_SECRET_NAME__
46-
- name: CLOUDFLARE_API_KEY
47-
valueFrom:
48-
secretKeyRef:
49-
key: CLOUDFLARE_API_KEY
50-
name: __MY_SECRET_NAME__
51-
- name: LETS_ENCRYPT_EMAIL
52-
valueFrom:
53-
secretKeyRef:
54-
key: LETS_ENCRYPT_EMAIL
55-
name: __MY_SECRET_NAME__
56-
- name: LETS_ENCRYPT_AGREE_TO_TOS
57-
valueFrom:
58-
secretKeyRef:
59-
key: LETS_ENCRYPT_AGREE_TO_TOS
60-
name: __MY_SECRET_NAME__
61-
- name: GOOGLE_CLOUD_BUCKET_NAME
62-
valueFrom:
63-
secretKeyRef:
64-
key: GOOGLE_CLOUD_BUCKET_NAME
65-
name: __MY_SECRET_NAME__
66-
- name: GOOGLE_CLOUD_PROJECT_ID
67-
valueFrom:
68-
secretKeyRef:
69-
key: GOOGLE_CLOUD_PROJECT_ID
70-
name: __MY_SECRET_NAME__
71-
- name: GOOGLE_CLOUD_CERT_DB_FILE
72-
valueFrom:
73-
secretKeyRef:
74-
key: GOOGLE_CLOUD_CERT_DB_FILE
75-
name: __MY_SECRET_NAME__
76-
- name: GOOGLE_CLOUD_CLIENT_EMAIL
77-
valueFrom:
78-
secretKeyRef:
79-
key: GOOGLE_CLOUD_CLIENT_EMAIL
80-
name: __MY_SECRET_NAME__
81-
- name: GOOGLE_CLOUD_PRIVATE_KEY
82-
valueFrom:
83-
secretKeyRef:
84-
key: GOOGLE_CLOUD_PRIVATE_KEY
85-
name: __MY_SECRET_NAME__
86-
- name: ENABLE_SSL
87-
valueFrom:
88-
secretKeyRef:
89-
key: ENABLE_SSL
90-
name: __MY_SECRET_NAME__
91-
image: interactivetraining/self-hosted-unpkg:latest
92-
imagePullPolicy: Always
93-
name: self-hosted-unpkg
94-
```
15+
```bash
16+
docker run -it --rm -p 443:443 -p 80:80 --env-file ./.env --name self-hosted-unpkg interactivetraining/self-hosted-unpkg
17+
```

‎build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
3+
while [[ "$#" -gt 0 ]]; do case 1ドル in
4+
-v|--version) version="2ドル"; shift;;
5+
*) echo "Unknown parameter passed: 1ドル"; exit 1;;
6+
esac; shift; done
7+
8+
npm run build
9+
docker build -t "interactivetraining/self-hosted-unpkg:$version" .
10+
docker push "interactivetraining/self-hosted-unpkg:$version"

‎http.sample.env

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ENABLE_SSL=0
2+
NPM_REGISTRY=https://registry.npmjs.com
3+
NPM_USER=
4+
NPM_PASSWORD=
5+
NPM_TOKEN=
6+
PORT=80
7+
REDIS_HOST=
8+
REDIS_PORT=6379
9+
REDIS_PASSWORD=
10+
CACHE_PREFIX=unpkg
11+
LOG_REQUEST=true
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
DOMAIN=my-self-hosted-unpkg-domain.com
2-
ENABLE_SSL=0
3-
NPM_REGISTRY=https://private.npm.registry
2+
ENABLE_SSL=1
3+
NPM_REGISTRY=https://registry.npmjs.com
44
NPM_USER=
55
NPM_PASSWORD=
66
NPM_TOKEN=
@@ -10,6 +10,11 @@ LETS_ENCRYPT_EMAIL=
1010
LETS_ENCRYPT_AGREE_TO_TOS=true
1111
GOOGLE_CLOUD_BUCKET_NAME=my-certs
1212
GOOGLE_CLOUD_PROJECT_ID=my-google-cloud-project-id
13-
GOOGLE_CLOUD_CERT_DB_FILE=cert-db.json
1413
GOOGLE_CLOUD_CLIENT_EMAIL=client-email@my-google-cloud-project-id.iam.gserviceaccount.com
1514
GOOGLE_CLOUD_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nEXAMPLE_PRIVATE_KEY\n-----END PRIVATE KEY-----\n"
15+
PORT=80
16+
REDIS_HOST=
17+
REDIS_PORT=6379
18+
REDIS_PASSWORD=
19+
CACHE_PREFIX=unpkg
20+
LOG_REQUEST=true

‎package.json

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,31 @@
1212
"build": "tsc"
1313
},
1414
"dependencies": {
15-
"@interactivetraining/le-challenge-cloudflare": "1.3.1",
16-
"@interactivetraining/le-store-gcloud-storage": "0.0.2",
15+
"@interactivetraining/acme-client": "0.0.6",
1716
"compression": "^1.7.3",
1817
"cors": "^2.8.5",
1918
"dotenv": "^5.0.1",
20-
"download-npm-package": "^3.1.12",
21-
"download-package-tarball": "^1.0.7",
2219
"express": "^4.16.4",
23-
"get-package-json-from-registry": "^2.2.1",
24-
"got": "^9.6.0",
25-
"greenlock-express": "^2.6.8",
20+
"gunzip-maybe": "^1.4.1",
2621
"helmet": "^3.16.0",
27-
"le-challenge-cloudflare": "^1.0.1",
2822
"mime": "^2.4.0",
23+
"mime-types": "^2.1.24",
2924
"redirect-https": "^1.3.0",
30-
"zlib": "^1.0.5"
25+
"tar-stream": "^2.1.0",
26+
"zlib": "^1.0.5",
27+
"ioredis": "^4.14.0"
3128
},
3229
"devDependencies": {
3330
"@types/compression": "0.0.36",
3431
"@types/cors": "^2.8.4",
3532
"@types/dotenv": "^6.1.0",
3633
"@types/express": "^4.16.1",
3734
"@types/helmet": "0.0.43",
38-
"@types/node": "^11.11.1",
39-
"@types/shelljs": "^0.8.3",
35+
"@types/node": "^12.7.2",
36+
"@types/tar-stream": "^1.6.1",
4037
"nodemon": "^1.18.10",
41-
"shelljs": "^0.8.3",
4238
"ts-node": "^8.0.2",
43-
"typescript": "^3.3.3333"
39+
"typescript": "^3.5.3",
40+
"@types/ioredis": "^4.0.15"
4441
}
4542
}

‎src/cache.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as Redis from 'ioredis';
2+
import {IPackageParams} from './interfaces';
3+
4+
const redis = (process.env.REDIS_PORT && process.env.REDIS_HOST) ? new Redis({
5+
port: parseInt(process.env.REDIS_PORT),
6+
host: process.env.REDIS_HOST,
7+
password: process.env.REDIS_PASSWORD
8+
}) : undefined;
9+
10+
export class Cache {
11+
static get(key: string): Promise<string | null> {
12+
return new Promise((resolve, reject) => {
13+
if (!redis) resolve(null);
14+
redis.get(key, (err, result) => {
15+
(err) ? reject(err) : resolve(result);
16+
});
17+
})
18+
}
19+
20+
static set(key: string, value: any, expireSeconds: number = 0): Promise<string> {
21+
if (!redis) return;
22+
return redis.set(key, value, 'EX', expireSeconds);
23+
}
24+
25+
static buildKey(pkg: IPackageParams): string {
26+
return `${process.env.CACHE_PREFIX}/cache/${(pkg.scope) ? `${pkg.scope}/` : ''}${pkg.package}/${pkg.version}/${pkg['0']}`;
27+
}
28+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /