Skip to content

Commit c57a840

Browse files
committed
some fixes and improvements, password reset not working
1 parent 18c6108 commit c57a840

File tree

11 files changed

+106
-49
lines changed

11 files changed

+106
-49
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ifeq ($(CMD_ARCH_GOAL),)
99
S9PK := $(PACKAGE_ID).s9pk
1010
else
1111
RAW_ARCH := $(firstword $(CMD_ARCH_GOAL))
12-
ACTUAL_ARCH := $(subst x86,x86_64,$(subst arm,aarch64,$(RAW_ARCH)))
12+
ACTUAL_ARCH := $(patsubst x86,x86_64,$(patsubst arm,aarch64,$(RAW_ARCH)))
1313
BUILD := $(ACTUAL_ARCH)
1414
S9PK := $(PACKAGE_ID)_$(BUILD).s9pk
1515
endif
File renamed without changes.

startos/actions/config.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ export const inputSpec = InputSpec.of({
4141
},
4242
}),
4343
}),
44+
max_upload_size: Value.number({
45+
name: 'Max Upload Size',
46+
description:
47+
'The maximum file size that is permitted to be uploaded by users to your homeserver.',
48+
required: true,
49+
default: 50,
50+
units: 'MB',
51+
integer: true,
52+
min: 1,
53+
max: 2000,
54+
}),
4455
smtp: sdk.inputSpecConstants.smtpInputSpec,
4556
})
4657

@@ -67,7 +78,12 @@ export const config = sdk.Action.withInput(
6778
if (!yaml) {
6879
return {}
6980
}
70-
const { enable_registration, listeners, federation_domain_whitelist } = yaml
81+
const {
82+
enable_registration,
83+
listeners,
84+
federation_domain_whitelist,
85+
max_upload_size,
86+
} = yaml
7187

7288
return {
7389
registration: enable_registration
@@ -79,6 +95,7 @@ export const config = sdk.Action.withInput(
7995
value: { federation_domain_whitelist },
8096
}
8197
: { selection: 'disabled' as const, value: {} },
98+
max_upload_size: toMB(max_upload_size),
8299
smtp: (await store.read((s) => s.smtp).const(effects)) || undefined,
83100
}
84101
},
@@ -108,6 +125,21 @@ export const config = sdk.Action.withInput(
108125
: input.federation.value.federation_domain_whitelist.length
109126
? input.federation.value.federation_domain_whitelist
110127
: undefined,
128+
max_upload_size: `${input.max_upload_size}M`,
111129
})
112130
},
113131
)
132+
133+
function toMB(max_upload_size: string): number {
134+
const unit = max_upload_size.at(-1)
135+
const value = Number(max_upload_size.slice(0, -1))
136+
137+
switch (unit) {
138+
case 'M':
139+
return value
140+
case 'G':
141+
return value / 1000
142+
default:
143+
return 1
144+
}
145+
}

startos/actions/resetAdmin.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,34 @@ export const resetAdmin = sdk.Action.withoutInput(
3838
const adminUserCreated = await store.read((s) => s.adminUserCreated).once()
3939

4040
if (adminUserCreated) {
41-
await sdk.SubContainer.withTemp(
41+
const passwordHash = await sdk.SubContainer.withTemp(
4242
effects,
4343
{ imageId: 'synapse' },
4444
mount,
45-
'update-admin-pass',
46-
async (subc) => {
47-
const passwordHash = (
45+
'get-password-hash',
46+
async (subc) =>
47+
(
4848
await subc.execFail([
4949
'hash_password',
5050
'-p',
5151
password,
5252
'-c',
5353
'/data/homeserver.yaml',
5454
])
55-
).stdout
56-
await subc.execFail([
55+
).stdout,
56+
)
57+
58+
await sdk.SubContainer.withTemp(
59+
effects,
60+
{ imageId: 'sqlite3' },
61+
mount,
62+
'save-password-hash',
63+
(subc) =>
64+
subc.execFail([
5765
'sqlite3',
5866
'/data/homeserver.db',
59-
`UPDATE users SET password_hash='${passwordHash}' WHERE name='${username}'`,
60-
])
61-
},
67+
`UPDATE users SET password_hash = "${passwordHash}" WHERE name = (SELECT name FROM users ORDER BY creation_ts ASC LIMIT 1)`,
68+
]),
6269
)
6370
} else {
6471
await sdk.SubContainer.withTemp(
@@ -93,7 +100,7 @@ export const resetAdmin = sdk.Action.withoutInput(
93100
name: 'Username',
94101
description: null,
95102
value: username,
96-
masked: true,
103+
masked: false,
97104
copyable: true,
98105
qr: false,
99106
},

startos/actions/setServerName.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,15 @@ export async function getSynapseInterfaceUrls(
8787
values: Record<string, string>
8888
}> {
8989
const iface = await sdk.serviceInterface.getOwn(effects, 'homeserver').once()
90+
9091
const hostnames =
91-
iface?.addressInfo
92-
?.filter(
93-
{
94-
visibility: 'public',
95-
...(type === 'tor'
96-
? { kind: 'onion' }
97-
: { exclude: { kind: 'onion' } }),
98-
},
99-
'url',
92+
iface?.addressInfo?.publicHostnames
93+
.filter((h) =>
94+
type === 'tor'
95+
? h.kind === 'onion'
96+
: h.kind === 'ip' && h.hostname.kind === 'domain',
10097
)
101-
.map((u) => u.hostname) || []
102-
// TODO: handle server port?
98+
.map((h) => h.hostname.value) || []
10399

104100
return {
105101
name,

startos/fileModels/homeserver.yml.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
pid_file,
1515
report_stats,
1616
suppress_key_server_warning,
17+
max_upload_size,
1718
} = configDefaults
1819
const { bind_addresses, port, resources, tls, type, x_forwarded } = listeners[0]
1920
const resource = resources[0]
@@ -75,6 +76,14 @@ const shape = object({
7576
form_secret: string.optional(),
7677
macaroon_secret_key: string.optional(),
7778
registration_shared_secret: string.optional(),
79+
max_upload_size: string
80+
.map((s) =>
81+
['B', 'K', 'M', 'G'].includes(s.at(-1) || '') &&
82+
typeof Number(s.slice(0, -1)) === 'number'
83+
? s
84+
: max_upload_size,
85+
)
86+
.onMismatch(max_upload_size),
7887
})
7988

8089
export type HomeserverYaml = typeof shape._TYPE

startos/install/versionGraph.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { current, other } from './versions'
33
import { configDefaults, mount } from '../utils'
44
import { sdk } from '../sdk'
55
import { homeserverYaml } from '../fileModels/homeserver.yml'
6+
import { homeserverLogConfig } from '../fileModels/homeserver.log.config'
7+
import { store } from '../fileModels/store.json'
68

79
export const versionGraph = VersionGraph.of({
810
current,
@@ -23,6 +25,15 @@ export const versionGraph = VersionGraph.of({
2325
}),
2426
)
2527

28+
await store.write(effects, {
29+
adminUserCreated: false,
30+
serverStarted: false,
31+
smtp: {
32+
selection: 'disabled',
33+
value: {},
34+
},
35+
})
2636
await homeserverYaml.merge(effects, configDefaults)
37+
await homeserverLogConfig.merge(effects, {})
2738
},
2839
})

startos/interfaces.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ export const setInterfaces = sdk.setupInterfaces(async ({ effects }) => {
66
const homeserverMulti = sdk.MultiHost.of(effects, 'homeserver-multi')
77
const homeserverMultiOrigin = await homeserverMulti.bindPort(nginxPort, {
88
protocol: 'http',
9-
// addSsl: { preferredExternalPort: 8448 }, // @TODO Aiden does this actually work?
109
})
1110
const homeserver = sdk.createInterface(effects, {
1211
name: 'Homeserver',
1312
id: 'homeserver',
1413
description: 'Your Matrix homeserver instance',
15-
type: 'ui',
14+
type: 'api',
1615
masked: false,
1716
schemeOverride: null,
1817
username: null,

startos/main.ts

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { sdk } from './sdk'
2-
import { adminPort, homeserverPort, nginxPort } from './utils'
2+
import { adminPort, homeserverPort, mount, nginxPort } from './utils'
33
import { homeserverYaml } from './fileModels/homeserver.yml'
4-
import { homeserverLogConfig } from './fileModels/homeserver.log.config'
54
import * as fs from 'node:fs/promises'
65
import { store } from './fileModels/store.json'
76

@@ -13,24 +12,25 @@ export const main = sdk.setupMain(async ({ effects, started }) => {
1312
*/
1413
console.info('[i] Starting Synapse!')
1514

16-
// Merge to homeserver.yaml to enforce file model protections
17-
await homeserverYaml.merge(effects, {})
18-
await homeserverLogConfig.merge(effects, {})
15+
// Read from homeserver.yaml with const() to ensure service restart if the file changes
16+
const config = await homeserverYaml.read().const(effects)
17+
18+
if (!config) {
19+
throw new Error('homeserver.yaml not found')
20+
}
21+
1922
const subcontainer = await sdk.SubContainer.of(
2023
effects,
2124
{ imageId: 'synapse' },
22-
sdk.Mounts.of().mountVolume({
23-
volumeId: 'main',
24-
subpath: null,
25-
mountpoint: '/data',
26-
readonly: false,
27-
}),
28-
'synapse',
25+
mount,
26+
'synapse-sub',
2927
)
3028
await subcontainer
3129
.exec(['chown', '-R', '991:991', '/data'])
3230
.then((a) => a.throw())
3331

32+
await store.merge(effects, { serverStarted: true })
33+
3434
const smtp = await store.read((s) => s.smtp).const(effects)
3535
if (smtp) {
3636
const creds =
@@ -57,9 +57,6 @@ export const main = sdk.setupMain(async ({ effects, started }) => {
5757
}
5858
}
5959

60-
// Read from homeserver.yaml with const() to ensure service restart if the file changes
61-
const config = await homeserverYaml.read().const(effects)
62-
6360
// create and configure nginx container
6461
const nginxContainer = await sdk.SubContainer.of(
6562
effects,
@@ -80,7 +77,7 @@ server {
8077
8178
location = /.well-known/matrix/server {
8279
default_type application/json;
83-
return 200 '{ "m.server": "${config?.server_name}:443" }';
80+
return 200 '{ "m.server": "${config.server_name}:443" }';
8481
}
8582
8683
location / {
@@ -89,7 +86,7 @@ server {
8986
9087
location ~* ^(\/_matrix|\/_synapse\/client|\/_synapse\/admin) {
9188
proxy_pass http://localhost:8008;
92-
client_max_body_size 50M; # TODO: make this configurable
89+
client_max_body_size ${config.max_upload_size};
9390
}
9491
9592
error_page 500 502 503 504 /50x.html;
@@ -112,7 +109,7 @@ server {
112109
113110
location = /config.json {
114111
default_type application/json;
115-
return 200 '{ "restrictBaseUrl": "https://${config?.server_name}" }';
112+
return 200 '{ "restrictBaseUrl": "https://${config.server_name}" }';
116113
}
117114
118115
error_page 500 502 503 504 /50x.html;
@@ -136,7 +133,7 @@ server {
136133
exec: { command: ['/start.py'] },
137134
ready: {
138135
display: 'Homeserver',
139-
gracePeriod: 10000,
136+
gracePeriod: 15000,
140137
fn: () =>
141138
sdk.healthCheck.checkWebUrl(
142139
effects,
@@ -165,16 +162,15 @@ server {
165162
.addHealthCheck('admin-interface', {
166163
ready: {
167164
display: 'Admin Dashboard',
168-
fn: () => {
169-
return sdk.healthCheck.checkWebUrl(
165+
fn: () =>
166+
sdk.healthCheck.checkWebUrl(
170167
effects,
171168
`http://localhost:${adminPort}`,
172169
{
173170
successMessage: `Running`,
174171
errorMessage: `Unreachable`,
175172
},
176-
)
177-
},
173+
),
178174
},
179175
requires: ['nginx'],
180176
})

startos/manifest.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ export const manifest = setupManifest({
3636
},
3737
arch: architectures,
3838
} as SDKImageInputSpec,
39+
sqlite3: {
40+
source: {
41+
dockerTag: 'alpine/sqlite',
42+
},
43+
arch: architectures,
44+
} as SDKImageInputSpec,
3945
},
4046
hardwareRequirements: {
4147
arch: architectures,

0 commit comments

Comments
 (0)