Skip to content

Commit

Permalink
Merge pull request #104 from u1-liquid/setup-host
Browse files Browse the repository at this point in the history
spec(misskey-host): MisskeyHostのカスタム
  • Loading branch information
riku6460 authored Jul 22, 2023
2 parents 4e24aff + becfdc2 commit cd448bb
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 655 deletions.
17 changes: 17 additions & 0 deletions .config/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,23 @@ redis:
# index: ''
# scope: local

# ┌────────────────────────────────────┐
#───┘ File storage (Drive) configuration └──────────────────────

#s3:
# baseUrl: s3.example.com
# bucket: example-bucket
# prefix: example-prefix
# endpoint: s3.example.com
# region: us-east-1
# useSSL: true
# accessKey: example-access-key
# secretKey: example-secret-key
# options:
# setPublicRead: true
# forcePathStyle: false
# useProxy: false

# ┌───────────────┐
#───┘ ID generation └───────────────────────────────────────────

Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/docker-host.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Publish Docker image (host)

on:
push:
tags:
- "**"

workflow_dispatch:

jobs:
push_to_registry:
name: Push Docker image to GitHub Container Registry
runs-on: ubuntu-22.04
if: github.repository == 'MisskeyIO/misskey'
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
platforms: linux/amd64
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/misskeyio/misskey
- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
echo "FORMATTED_BRANCH_NAME=$(echo ${{ github.ref_name }} | sed -e 's/\//-/g' )" >> $GITHUB_ENV
- name: Build and Push to GitHub Container Registry
uses: docker/build-push-action@v4
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
labels: ${{ env.FORMATTED_BRANCH_NAME }}
cache-from: type=gha
cache-to: type=gha,mode=max
tags: |
ghcr.io/misskeyio/misskey:host
ghcr.io/misskeyio/misskey:${{ env.FORMATTED_BRANCH_NAME }}
13 changes: 0 additions & 13 deletions .github/workflows/reviewer_lottery.yml

This file was deleted.

112 changes: 0 additions & 112 deletions .github/workflows/storybook.yml

This file was deleted.

15 changes: 15 additions & 0 deletions packages/backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ export type Source = {
index: string;
scope?: 'local' | 'global' | string[];
};
s3?: {
baseUrl: string;
bucket: string;
prefix: string;
endpoint: string;
region?: string;
useSSL: boolean;
accessKey: string;
secretKey: string;
options?: {
setPublicRead?: boolean;
forcePathStyle?: boolean;
useProxy?: boolean;
}
};

proxy?: string;
proxySmtp?: string;
Expand Down
27 changes: 11 additions & 16 deletions packages/backend/src/core/DriveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,7 @@ export class DriveService {
// thunbnail, webpublic を必要なら生成
const alts = await this.generateAlts(path, type, !file.uri);

const meta = await this.metaService.fetch();

if (meta.useObjectStorage) {
if (this.config.s3) {
//#region ObjectStorage params
let [ext] = (name.match(/\.([a-zA-Z0-9_-]+)$/) ?? ['']);

Expand All @@ -158,11 +156,11 @@ export class DriveService {
ext = '';
}

const baseUrl = meta.objectStorageBaseUrl
?? `${ meta.objectStorageUseSSL ? 'https' : 'http' }://${ meta.objectStorageEndpoint }${ meta.objectStoragePort ? `:${meta.objectStoragePort}` : '' }/${ meta.objectStorageBucket }`;
const baseUrl = this.config.s3.baseUrl
?? `${ this.config.s3.useSSL ? 'https' : 'http' }://${ this.config.s3.endpoint }/${ this.config.s3.bucket }`;

// for original
const key = `${meta.objectStoragePrefix}/${randomUUID()}${ext}`;
const key = `${this.config.s3.prefix}/${randomUUID()}${ext}`;
const url = `${ baseUrl }/${ key }`;

// for alts
Expand All @@ -179,15 +177,15 @@ export class DriveService {
];

if (alts.webpublic) {
webpublicKey = `${meta.objectStoragePrefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicKey = `${this.config.s3.prefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicUrl = `${ baseUrl }/${ webpublicKey }`;

this.registerLogger.info(`uploading webpublic: ${webpublicKey}`);
uploads.push(this.upload(webpublicKey, alts.webpublic.data, alts.webpublic.type, alts.webpublic.ext, name));
}

if (alts.thumbnail) {
thumbnailKey = `${meta.objectStoragePrefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailKey = `${this.config.s3.prefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailUrl = `${ baseUrl }/${ thumbnailKey }`;

this.registerLogger.info(`uploading thumbnail: ${thumbnailKey}`);
Expand Down Expand Up @@ -364,10 +362,8 @@ export class DriveService {
if (type === 'image/apng') type = 'image/png';
if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream';

const meta = await this.metaService.fetch();

const params = {
Bucket: meta.objectStorageBucket,
Bucket: this.config.s3?.bucket,
Key: key,
Body: stream,
ContentType: type,
Expand All @@ -380,9 +376,9 @@ export class DriveService {
// 許可されているファイル形式でしか拡張子をつけない
ext ? correctFilename(filename, ext) : filename,
);
if (meta.objectStorageSetPublicRead) params.ACL = 'public-read';
if (this.config.s3?.options?.setPublicRead) params.ACL = 'public-read';

await this.s3Service.upload(meta, params)
await this.s3Service.upload(params)
.then(
result => {
if ('Bucket' in result) { // CompleteMultipartUploadCommandOutput
Expand Down Expand Up @@ -734,14 +730,13 @@ export class DriveService {

@bindThis
public async deleteObjectStorageFile(key: string) {
const meta = await this.metaService.fetch();
try {
const param = {
Bucket: meta.objectStorageBucket,
Bucket: this.config.s3?.bucket,
Key: key,
} as DeleteObjectCommandInput;

await this.s3Service.delete(meta, param);
await this.s3Service.delete(param);
} catch (err: any) {
if (err.name === 'NoSuchKey') {
this.deleteLogger.warn(`The object storage had no such key to delete: ${key}. Skipping this.`, err as Error);
Expand Down
33 changes: 15 additions & 18 deletions packages/backend/src/core/S3Service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Upload } from '@aws-sdk/lib-storage';
import { NodeHttpHandler, NodeHttpHandlerOptions } from '@aws-sdk/node-http-handler';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import type { Meta } from '@/models/entities/Meta.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { bindThis } from '@/decorators.js';
import type { DeleteObjectCommandInput, PutObjectCommandInput } from '@aws-sdk/client-s3';
Expand All @@ -23,35 +22,33 @@ export class S3Service {
}

@bindThis
public getS3Client(meta: Meta): S3Client {
const u = meta.objectStorageEndpoint
? `${meta.objectStorageUseSSL ? 'https' : 'http'}://${meta.objectStorageEndpoint}`
: `${meta.objectStorageUseSSL ? 'https' : 'http'}://example.net`; // dummy url to select http(s) agent
public getS3Client(): S3Client {
const u = `${this.config.s3?.useSSL ? 'https' : 'http'}://${this.config.s3?.endpoint ?? 'example.net'}`; // dummy url to select http(s) agent

const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy);
const agent = this.httpRequestService.getAgentByUrl(new URL(u), !this.config.s3?.options?.useProxy);
const handlerOption: NodeHttpHandlerOptions = {};
if (meta.objectStorageUseSSL) {
if (this.config.s3?.useSSL) {
handlerOption.httpsAgent = agent as https.Agent;
} else {
handlerOption.httpAgent = agent as http.Agent;
}

return new S3Client({
endpoint: meta.objectStorageEndpoint ? u : undefined,
credentials: (meta.objectStorageAccessKey !== null && meta.objectStorageSecretKey !== null) ? {
accessKeyId: meta.objectStorageAccessKey,
secretAccessKey: meta.objectStorageSecretKey,
endpoint: this.config.s3?.endpoint ? u : undefined,
credentials: (this.config.s3 && (this.config.s3.accessKey !== null && this.config.s3.secretKey !== null)) ? {
accessKeyId: this.config.s3.accessKey,
secretAccessKey: this.config.s3.secretKey,
} : undefined,
region: meta.objectStorageRegion ? meta.objectStorageRegion : undefined, // 空文字列もundefinedにするため ?? は使わない
tls: meta.objectStorageUseSSL,
forcePathStyle: meta.objectStorageEndpoint ? meta.objectStorageS3ForcePathStyle : false, // AWS with endPoint omitted
region: this.config.s3?.region ?? 'us-east-1',
tls: this.config.s3?.useSSL,
forcePathStyle: this.config.s3?.options?.forcePathStyle ?? false, // AWS with endPoint omitted
requestHandler: new NodeHttpHandler(handlerOption),
});
}

@bindThis
public async upload(meta: Meta, input: PutObjectCommandInput) {
const client = this.getS3Client(meta);
public async upload(input: PutObjectCommandInput) {
const client = this.getS3Client();
return new Upload({
client,
params: input,
Expand All @@ -62,8 +59,8 @@ export class S3Service {
}

@bindThis
public delete(meta: Meta, input: DeleteObjectCommandInput) {
const client = this.getS3Client(meta);
public delete(input: DeleteObjectCommandInput) {
const client = this.getS3Client();
return client.send(new DeleteObjectCommand(input));
}
}
Loading

0 comments on commit cd448bb

Please sign in to comment.