* refactor: enhance rewrite configuration handling by introducing safe name validation and custom rewrite existence checks
* test: cover custom rewrite name handling
The auto-renew flow in obtainSSL returned early when OpenResty was not
installed or `nginx -s reload` failed, skipping reloadSystemSSL. The new
certificate was persisted to the DB and written into website Nginx
configs, but the panel's own server.crt / server.key on disk and the
in-memory constant.CertStore were left pointing at the old material.
Because the cert was now fresh, subsequent cron ticks did not retry the
renewal, so the panel kept serving the stale cert until a user manually
re-applied it from 面板设置 → SSL.
Two changes:
1. agent/app/service/website_ssl.go
reloadSystemSSL is now called unconditionally after a successful
renewal, regardless of whether OpenResty is present or nginx reload
succeeded. The function already short-circuits for non-panel SSLs,
so this is safe.
2. agent/app/service/website_ssl.go + agent/cron/job/ssl.go
Add SyncSystemSSL, invoked at the start of every renew cron tick.
It compares the panel's on-disk cert/key with the WebsiteSSL row
referenced by the SSLID setting and rewrites the files + notifies
core when they diverge. This recovers existing installs that are
already in the "DB ahead of disk" state and self-heals any future
drift introduced by transient failures.
https://github.com/1Panel-dev/1Panel/issues/12472
#### What this PR does / why we need it?
Refs https://github.com/1Panel-dev/1Panel/issues/12681
#### Summary of your change
#### Please indicate you've done the following:
- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
Enabling Panel SSL with the self-sign provider rejected IPv6 hosts with
"domain format invalid". Two coupled bugs caused this:
1. The frontend extracted the host from window.location.href with
href.split('//')[1].split(':')[0]. For an IPv6 URL like
https://[::1]:1234 that yields '[' \u2014 not a valid host \u2014 because
the second split splits on the first colon inside the bracketed
address. Use window.location.hostname, which natively returns the
bracket-stripped IPv6 host.
2. The backend ObtainSSL flow used net.ParseIP(domain) directly. Even if
the frontend sent the bracketed form ('[::1]'), net.ParseIP rejects
brackets, so the value flowed into IsValidDomain() and failed the
regex.
Add common.ParseIPLoose() that accepts both bare and bracketed IPv6 in
addition to bare IPv4. Use it at both call sites in ObtainSSL (renew
path and create path). A unit test guards the regression.
Files:
- agent/utils/common/common.go (new ParseIPLoose helper)
- agent/utils/common/parse_ip_test.go (12 cases, all green)
- agent/app/service/website_ca.go (call sites switched)
- frontend/src/views/setting/safe/ssl/index.vue
(host extraction fix)
Fixes#12646
Signed-off-by: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com>
`NewIFileService` returns the bare struct type `FileService`, but its
body returns a pointer (`&FileService{}`), and the function name suggests
it should return the interface (`IFileService`). The current signature
breaks `go build ./...` on the `agent` module:
app/service/file.go:95:9: cannot use &FileService{} (value of type
*FileService) as FileService value in return statement
app/service/website_proxy.go:276:36: cannot call pointer method
GetFileList on FileService
Both errors resolve when the constructor returns the interface, since
`*FileService` implements every method on `IFileService` (verified with
`go vet ./...`).
After this change, `go build ./...` and `go vet ./...` are clean on the
`agent` module.