diff --git a/appview/config/config.go b/appview/config/config.go index 36a66a68..20369cf8 100644 --- a/appview/config/config.go +++ b/appview/config/config.go @@ -163,6 +163,10 @@ type SSHConfig struct { HostKeyPath string `env:"HOST_KEY_PATH"` } +type PorxieConfig struct { + Url string `env:"URL"` // appview will default to PDS when porxie url is not configured +} + func (cfg RedisConfig) ToURL() string { u := &url.URL{ Scheme: "redis", @@ -198,6 +202,7 @@ type Config struct { KnotMirror KnotMirrorConfig `env:",prefix=TANGLED_KNOTMIRROR_"` Ogre OgreConfig `env:",prefix=TANGLED_OGRE_"` SSH SSHConfig `env:",prefix=TANGLED_SSH_"` + Porxie PorxieConfig `env:",prefix=TANGLED_PORXIE_"` } func LoadConfig(ctx context.Context) (*Config, error) { diff --git a/appview/state/state.go b/appview/state/state.go index 8a40d158..cf9d22af 100644 --- a/appview/state/state.go +++ b/appview/state/state.go @@ -129,7 +129,12 @@ func Make(ctx context.Context, config *config.Config) (*State, error) { mentionsResolver := mentions.New(config, res, d, log.SubLogger(logger, "mentionsResolver")) - blobStore := blobstore.NewPdsBlobStore(res.Directory()) + var blobStore blobstore.BlobStore + if config.Porxie.Url != "" { + blobStore = blobstore.NewPorxieBlobStore(config.Porxie.Url) + } else { + blobStore = blobstore.NewPdsBlobStore(res.Directory()) + } jc, err := jetstream.NewJetstreamClient( config.Jetstream.Endpoint, diff --git a/blobstore/porxie.go b/blobstore/porxie.go new file mode 100644 index 00000000..9f867480 --- /dev/null +++ b/blobstore/porxie.go @@ -0,0 +1,33 @@ +package blobstore + +import ( + "context" + "fmt" + "io" + "net/http" + + "github.com/bluesky-social/indigo/atproto/syntax" + "github.com/ipfs/go-cid" +) + +type Porxie struct { + url string +} + +func NewPorxieBlobStore(url string) *Porxie { + return &Porxie{url} +} + +func (s *Porxie) GetBlob(ctx context.Context, did syntax.DID, cid cid.Cid) (io.ReadCloser, error) { + url := fmt.Sprintf("%s/%s/%s", s.url, did, cid) + resp, err := http.Get(url) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status: %s", resp.Status) + } + + return resp.Body, nil +} diff --git a/flake.lock b/flake.lock index 1c5f8cb9..54b5ac15 100644 --- a/flake.lock +++ b/flake.lock @@ -183,11 +183,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1771848320, - "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", + "lastModified": 1777954456, + "narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2fc6539b481e1d2569f25f8799236694180c0993", + "rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1", "type": "github" }, "original": { diff --git a/nix/vm.nix b/nix/vm.nix index bef5a80b..64f0bd80 100644 --- a/nix/vm.nix +++ b/nix/vm.nix @@ -81,6 +81,11 @@ in host.port = 7100; guest.port = 7100; } + { + from = "host"; + host.port = 6314; + guest.port = 6314; + } ]; sharedDirectories = { # We can't use the 9p mounts directly for most of these @@ -155,6 +160,14 @@ in host all tnglr 127.0.0.1/32 trust ''; }; + services.porxie = { + enable = true; + settings = { + PORXIE_SERVER_ADDRESS = "ip:0.0.0.0:6314"; + PORXIE_BLOB_ALLOWED_MIMETYPES = ["application/gzip" "image/*" "text/plain"]; + PORXIE_IDENTITY_PLC_URL = plcUrl; + }; + }; services.tangled.knotmirror = { enable = true; knotSSRF = false;