Compare commits
8 Commits
7aa2a907d5
...
v1.3.26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3215da8a84 | ||
|
|
6f69697705 | ||
|
|
33cfc1a90d | ||
|
|
3e05c7fe49 | ||
|
|
924540d7a9 | ||
|
|
561816d79d | ||
|
|
cab78eb3d1 | ||
|
|
f61f82d36f |
14
go.mod
14
go.mod
@@ -18,7 +18,7 @@ require (
|
|||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/pressly/goose/v3 v3.27.1
|
github.com/pressly/goose/v3 v3.27.1
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
golang.org/x/crypto v0.53.0
|
golang.org/x/crypto v0.56.0
|
||||||
golang.org/x/oauth2 v0.36.0
|
golang.org/x/oauth2 v0.36.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,12 +80,12 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/mod v0.37.0 // indirect
|
golang.org/x/mod v0.38.0 // indirect
|
||||||
golang.org/x/net v0.56.0 // indirect
|
golang.org/x/net v0.57.0 // indirect
|
||||||
golang.org/x/sync v0.21.0 // indirect
|
golang.org/x/sync v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.46.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/text v0.39.0 // indirect
|
golang.org/x/text v0.41.0 // indirect
|
||||||
golang.org/x/tools v0.47.0 // indirect
|
golang.org/x/tools v0.48.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
rsc.io/binaryregexp v0.2.0 // indirect
|
rsc.io/binaryregexp v0.2.0 // indirect
|
||||||
|
|||||||
32
go.sum
32
go.sum
@@ -186,24 +186,24 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
|||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
|
||||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
|
||||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||||
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
|
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||||
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
|
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
8
management-ui/go.mod
Normal file
8
management-ui/go.mod
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Modul-Grenze, kein eigenständiges Go-Modul mit Code. Verhindert dass
|
||||||
|
// `go vet/build/test ./...` im Root-Modul in management-ui/node_modules/
|
||||||
|
// hineinläuft — npm-Pakete (z.B. flatted) shippen dort teils rohe .go-
|
||||||
|
// Dateien ohne eigenes go.mod, die sich bei jedem bun/npm install ändern
|
||||||
|
// können und sonst ungefragt in EdgeGuards Go-Quality-Gates landen.
|
||||||
|
module git.netcell-it.de/projekte/edgeguard-native/management-ui
|
||||||
|
|
||||||
|
go 1.26
|
||||||
@@ -438,7 +438,7 @@ export default function AlertsPage() {
|
|||||||
onChange: (keys) => setSelectedIds(keys as number[]),
|
onChange: (keys) => setSelectedIds(keys as number[]),
|
||||||
}}
|
}}
|
||||||
rowClassName={(r) => (r.acknowledged_at ? 'eg-row-muted' : '')}
|
rowClassName={(r) => (r.acknowledged_at ? 'eg-row-muted' : '')}
|
||||||
pagination={{ pageSize: 25 }}
|
pagination={{ defaultPageSize: 25 }}
|
||||||
locale={{ emptyText: (
|
locale={{ emptyText: (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
icon={<BellOutlined />}
|
icon={<BellOutlined />}
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ export default function HistoryTab() {
|
|||||||
loading={list.isFetching}
|
loading={list.isFetching}
|
||||||
dataSource={list.data ?? []}
|
dataSource={list.data ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 25, showSizeChanger: true, pageSizeOptions: [25, 50, 100] }}
|
pagination={{ defaultPageSize: 25, showSizeChanger: true, pageSizeOptions: [25, 50, 100] }}
|
||||||
locale={{ emptyText: t('backups.empty') }}
|
locale={{ emptyText: t('backups.empty') }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ function DecisionsTab() {
|
|||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
dataSource={decisions ?? []}
|
dataSource={decisions ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 20 }}
|
pagination={{ defaultPageSize: 20 }}
|
||||||
/>
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
title={t('cs.decision.banModal')}
|
title={t('cs.decision.banModal')}
|
||||||
@@ -321,7 +321,7 @@ function AlertsTab() {
|
|||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
dataSource={alerts ?? []}
|
dataSource={alerts ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 20 }}
|
pagination={{ defaultPageSize: 20 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -379,7 +379,7 @@ function BouncersTab() {
|
|||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
dataSource={bouncers ?? []}
|
dataSource={bouncers ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 20 }}
|
pagination={{ defaultPageSize: 20 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -436,7 +436,7 @@ function MachinesTab() {
|
|||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
dataSource={machines ?? []}
|
dataSource={machines ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 20 }}
|
pagination={{ defaultPageSize: 20 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -515,7 +515,7 @@ function CollectionsTab() {
|
|||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
dataSource={collections ?? []}
|
dataSource={collections ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 50 }}
|
pagination={{ defaultPageSize: 50 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -129,6 +129,12 @@ export default function FirewallLivePage() {
|
|||||||
pausedRef.current = paused
|
pausedRef.current = paused
|
||||||
const pendingDuringPauseRef = useRef<Entry[]>([])
|
const pendingDuringPauseRef = useRef<Entry[]>([])
|
||||||
const wsRef = useRef<WebSocket | null>(null)
|
const wsRef = useRef<WebSocket | null>(null)
|
||||||
|
// tRef statt `t` in den WS-Effect-Deps: `t` wechselt bei jedem
|
||||||
|
// i18n-Store-Update die Identität. Stünde es in den Deps, würde der
|
||||||
|
// Effect neu laufen — inkl. `setEntries([])` und WS-Reconnect, d. h.
|
||||||
|
// der Live-Puffer wäre ohne erkennbaren Grund plötzlich leer.
|
||||||
|
const tRef = useRef(t)
|
||||||
|
useEffect(() => { tRef.current = t }, [t])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const t = setTimeout(() => setAppliedFilters(filters), 300)
|
const t = setTimeout(() => setAppliedFilters(filters), 300)
|
||||||
@@ -187,7 +193,7 @@ export default function FirewallLivePage() {
|
|||||||
if (!cancelled && active) scheduleReconnect()
|
if (!cancelled && active) scheduleReconnect()
|
||||||
}
|
}
|
||||||
ws.onerror = () => {
|
ws.onerror = () => {
|
||||||
setError(t('fwlog.connError'))
|
setError(tRef.current('fwlog.connError'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +210,7 @@ export default function FirewallLivePage() {
|
|||||||
if (reconnectTimer) clearTimeout(reconnectTimer)
|
if (reconnectTimer) clearTimeout(reconnectTimer)
|
||||||
if (wsRef.current) { wsRef.current.close(); wsRef.current = null }
|
if (wsRef.current) { wsRef.current.close(); wsRef.current = null }
|
||||||
}
|
}
|
||||||
}, [active, query, t])
|
}, [active, query])
|
||||||
|
|
||||||
// Resume: gebufferte Events in die Tabelle mergen.
|
// Resume: gebufferte Events in die Tabelle mergen.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -412,7 +418,7 @@ export default function FirewallLivePage() {
|
|||||||
size="small"
|
size="small"
|
||||||
dataSource={[...entries].reverse()}
|
dataSource={[...entries].reverse()}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 50, showSizeChanger: true, pageSizeOptions: [25, 50, 100, 200] }}
|
pagination={{ defaultPageSize: 50, showSizeChanger: true, pageSizeOptions: [25, 50, 100, 200] }}
|
||||||
locale={{ emptyText: connected ? t('fwlog.empty') : t('fwlog.connecting') }}
|
locale={{ emptyText: connected ? t('fwlog.empty') : t('fwlog.connecting') }}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ export default function LogsPage() {
|
|||||||
loading={logsQuery.isFetching}
|
loading={logsQuery.isFetching}
|
||||||
dataSource={entries}
|
dataSource={entries}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ pageSize: 50, showSizeChanger: true, pageSizeOptions: [25, 50, 100, 200] }}
|
pagination={{ defaultPageSize: 50, showSizeChanger: true, pageSizeOptions: [25, 50, 100, 200] }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{entries.length === 0 && !logsQuery.isFetching && (
|
{entries.length === 0 && !logsQuery.isFetching && (
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export default function RoutesTab() {
|
|||||||
size="small"
|
size="small"
|
||||||
dataSource={live.data ?? []}
|
dataSource={live.data ?? []}
|
||||||
columns={liveColumns}
|
columns={liveColumns}
|
||||||
pagination={{ pageSize: 25, showSizeChanger: true, pageSizeOptions: [25, 50, 100] }}
|
pagination={{ defaultPageSize: 25, showSizeChanger: true, pageSizeOptions: [25, 50, 100] }}
|
||||||
locale={{ emptyText: t('routes.liveEmpty') }}
|
locale={{ emptyText: t('routes.liveEmpty') }}
|
||||||
style={{ marginTop: 12 }}
|
style={{ marginTop: 12 }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -302,9 +302,18 @@ SUDOERS
|
|||||||
# in die apt-Quelle. Ab jetzt publiziert publish.sh/release.sh nur
|
# in die apt-Quelle. Ab jetzt publiziert publish.sh/release.sh nur
|
||||||
# noch nach stable/testing — ohne diese Migration würden
|
# noch nach stable/testing — ohne diese Migration würden
|
||||||
# Bestandsnodes stumm keine neuen Updates mehr sehen (main bleibt
|
# Bestandsnodes stumm keine neuen Updates mehr sehen (main bleibt
|
||||||
# auf dem letzten main-Stand stehen). Idempotent: greift nur wenn
|
# auf dem letzten main-Stand stehen). Idempotent.
|
||||||
# die Datei existiert UND noch auf "main" zeigt.
|
#
|
||||||
|
# netcell-edgeguard.list: NOCH ältere Installer-Generation vor dem
|
||||||
|
# Rename auf edgeguard.list (install.sh räumt sie nur bei einem
|
||||||
|
# FRISCHEN Install auf, nie bei einem Upgrade — auf Bestandsnodes,
|
||||||
|
# die nie neu installiert wurden, ist sie ggf. noch die aktive
|
||||||
|
# Datei). Erst konsolidieren, dann main→stable.
|
||||||
EG_SOURCES_LIST=/etc/apt/sources.list.d/edgeguard.list
|
EG_SOURCES_LIST=/etc/apt/sources.list.d/edgeguard.list
|
||||||
|
EG_LEGACY_LIST=/etc/apt/sources.list.d/netcell-edgeguard.list
|
||||||
|
if [ -f "$EG_LEGACY_LIST" ] && [ ! -f "$EG_SOURCES_LIST" ]; then
|
||||||
|
mv "$EG_LEGACY_LIST" "$EG_SOURCES_LIST"
|
||||||
|
fi
|
||||||
if [ -f "$EG_SOURCES_LIST" ] && grep -q ' trixie main$' "$EG_SOURCES_LIST"; then
|
if [ -f "$EG_SOURCES_LIST" ] && grep -q ' trixie main$' "$EG_SOURCES_LIST"; then
|
||||||
sed -i 's/ trixie main$/ trixie stable/' "$EG_SOURCES_LIST"
|
sed -i 's/ trixie main$/ trixie stable/' "$EG_SOURCES_LIST"
|
||||||
apt-get update -qq || true
|
apt-get update -qq || true
|
||||||
@@ -401,9 +410,25 @@ SYSCTL
|
|||||||
if [ ! -f /var/log/edgeguard/firewall.jsonl ]; then
|
if [ ! -f /var/log/edgeguard/firewall.jsonl ]; then
|
||||||
: > /var/log/edgeguard/firewall.jsonl
|
: > /var/log/edgeguard/firewall.jsonl
|
||||||
fi
|
fi
|
||||||
# ulogd2 läuft als root (eigener Daemon); File muss von ihm
|
# WICHTIG (Incident 2026-09-06): ulogd2 läuft NICHT als root —
|
||||||
# schreibbar UND von edgeguard-API lesbar sein.
|
# die Debian-Unit startet `ulogd --daemon --uid ulog`, der Daemon
|
||||||
chown root:"$EG_USER" /var/log/edgeguard/firewall.jsonl
|
# dropped also nach dem Öffnen seiner Files auf den User `ulog`.
|
||||||
|
# Solange er läuft schreibt er über den offenen fd weiter, egal
|
||||||
|
# wem die Datei gehört. Aber: das Distro-Profil
|
||||||
|
# /etc/logrotate.d/ulogd2 schickt nachts SIGHUP an ulogd, damit
|
||||||
|
# es seine Logfiles neu öffnet — und DAS passiert als `ulog`.
|
||||||
|
# Gehörte die Datei root:edgeguard 0640, scheitert das Reopen mit
|
||||||
|
# "can't open JSON log file: Permission denied", ulogd wertet das
|
||||||
|
# als fatal und BEENDET sich. Ohne Restart= blieb der Dienst dann
|
||||||
|
# tagelang still tot (5 Tage unbemerkt) → Firewall-Live-Log zeigte
|
||||||
|
# nur noch den alten In-Memory-Ring der API, nie neue Events.
|
||||||
|
# Daher: Owner = ulog (Schreiber), Gruppe = edgeguard (Leser).
|
||||||
|
if getent passwd ulog >/dev/null 2>&1; then
|
||||||
|
chown ulog:"$EG_USER" /var/log/edgeguard/firewall.jsonl
|
||||||
|
else
|
||||||
|
# ulogd2 (noch) nicht installiert — Fallback wie bisher.
|
||||||
|
chown root:"$EG_USER" /var/log/edgeguard/firewall.jsonl
|
||||||
|
fi
|
||||||
chmod 0640 /var/log/edgeguard/firewall.jsonl
|
chmod 0640 /var/log/edgeguard/firewall.jsonl
|
||||||
|
|
||||||
cat > /etc/ulogd.conf <<'ULOGD'
|
cat > /etc/ulogd.conf <<'ULOGD'
|
||||||
@@ -451,7 +476,9 @@ ULOGD
|
|||||||
compress
|
compress
|
||||||
delaycompress
|
delaycompress
|
||||||
copytruncate
|
copytruncate
|
||||||
create 0640 root edgeguard
|
# Owner muss ulog sein — siehe Kommentar oben: ulogd re-öffnet die
|
||||||
|
# Datei bei SIGHUP als `ulog` und stirbt sonst an EACCES.
|
||||||
|
create 0640 ulog edgeguard
|
||||||
}
|
}
|
||||||
LOGROTATE
|
LOGROTATE
|
||||||
chmod 0644 /etc/logrotate.d/edgeguard-firewall
|
chmod 0644 /etc/logrotate.d/edgeguard-firewall
|
||||||
@@ -460,6 +487,18 @@ LOGROTATE
|
|||||||
# da ist (Dependency-Konflikt o.ä.), nur warnen — die Firewall
|
# da ist (Dependency-Konflikt o.ä.), nur warnen — die Firewall
|
||||||
# läuft auch ohne Logger.
|
# läuft auch ohne Logger.
|
||||||
if systemctl list-unit-files ulogd2.service >/dev/null 2>&1; then
|
if systemctl list-unit-files ulogd2.service >/dev/null 2>&1; then
|
||||||
|
# Restart=always als Selbstheilung: ulogd beendet sich bei
|
||||||
|
# einem fehlgeschlagenen Reopen mit Exit-Code 0 (also KEIN
|
||||||
|
# Restart=on-failure — das würde nicht greifen). Ohne das
|
||||||
|
# bleibt Firewall-Logging nach einem Rotate-Hiccup still tot.
|
||||||
|
install -d -m 0755 /etc/systemd/system/ulogd2.service.d
|
||||||
|
cat > /etc/systemd/system/ulogd2.service.d/edgeguard-restart.conf <<'ULOGDUNIT'
|
||||||
|
# Managed by edgeguard — re-installation overwrites this file.
|
||||||
|
[Service]
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5s
|
||||||
|
ULOGDUNIT
|
||||||
|
systemctl daemon-reload
|
||||||
systemctl enable ulogd2.service >/dev/null 2>&1 || true
|
systemctl enable ulogd2.service >/dev/null 2>&1 || true
|
||||||
systemctl restart ulogd2.service || \
|
systemctl restart ulogd2.service || \
|
||||||
echo "postinst: ulogd2.service restart failed (firewall logs disabled until fixed)" >&2
|
echo "postinst: ulogd2.service restart failed (firewall logs disabled until fixed)" >&2
|
||||||
|
|||||||
@@ -50,6 +50,15 @@ if [ -z "${GITEA_TOKEN:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
export GITEA_TOKEN
|
export GITEA_TOKEN
|
||||||
|
|
||||||
|
# `make ui` fällt bei fehlendem bun auf `npm install` zurück (Convenience
|
||||||
|
# für schnelle lokale Builds) — das löst Dependencies gegen package.json
|
||||||
|
# neu auf statt gegen das gepinnte management-ui/bun.lock, und hinterlässt
|
||||||
|
# eine package-lock.json die nichts mit dem committeten Lockfile zu tun
|
||||||
|
# hat. Für einen Release (Testing ODER Stable) ist das nicht akzeptabel —
|
||||||
|
# beide Kanäle müssen reproduzierbar aus dem gepinnten Lockfile bauen.
|
||||||
|
command -v bun >/dev/null 2>&1 || \
|
||||||
|
abort "bun fehlt — Release-Builds müssen aus management-ui/bun.lock bauen, nicht aus dem npm-Fallback. Installieren: https://bun.sh/install"
|
||||||
|
|
||||||
# ─── Testing-Version: datumsbasiert YYYY.MM.DD.NN ──────────────────────
|
# ─── Testing-Version: datumsbasiert YYYY.MM.DD.NN ──────────────────────
|
||||||
# NN = laufende Nummer für den Tag, ermittelt aus den bereits im Registry
|
# NN = laufende Nummer für den Tag, ermittelt aus den bereits im Registry
|
||||||
# vorhandenen Versionen des Meta-Pakets (edgeguard) mit dem heutigen
|
# vorhandenen Versionen des Meta-Pakets (edgeguard) mit dem heutigen
|
||||||
|
|||||||
Reference in New Issue
Block a user