diff --git a/Cargo.lock b/Cargo.lock
index 7f63f1eaf27cec61beeed2e581db25d5ec8ec364..43b8d55edcf7f7f8fe9c3d2853c1fa33c31c4b5a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1132,6 +1132,7 @@ dependencies = [
  "http",
  "log",
  "resiter",
+ "serde",
  "serde_urlencoded 0.7.0",
  "smallvec",
  "tokio",
diff --git a/app/lib/common-libs/programOptions.ts b/app/lib/common-libs/programOptions.ts
index 505cd5caf3bf14d1015f5c4a8cb100e95e70cf83..6ec4f1bb06caf846d0eb1f9995dd6e41042fb172 100644
--- a/app/lib/common-libs/programOptions.ts
+++ b/app/lib/common-libs/programOptions.ts
@@ -29,7 +29,7 @@ export interface ProgramOptions {
   sqlTraces?: boolean;
   memory?: boolean;
   gva?: boolean;
-  nogva?: boolean;
+  noGva?: boolean;
 }
 
 export const cliprogram: ProgramOptions = {
diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts
index a42a582fddeab8430bd776d8d707edf8f19c9196..0353b71176cc52226190ec4101cf0aa0c7d7468f 100644
--- a/app/lib/dal/fileDAL.ts
+++ b/app/lib/dal/fileDAL.ts
@@ -79,6 +79,7 @@ import { LevelDBIindex } from "./indexDAL/leveldb/LevelDBIindex";
 import { LevelDBMindex } from "./indexDAL/leveldb/LevelDBMindex";
 import { ConfDAO } from "./indexDAL/abstract/ConfDAO";
 import { ServerDAO } from "./server-dao";
+import { PeerDTO } from "../dto/PeerDTO";
 
 const readline = require("readline");
 const indexer = require("../indexer").Indexer;
@@ -233,12 +234,12 @@ export class FileDAL implements ServerDAO {
   }
 
   initRustServer(conf: ConfDTO, commandName: string | null = null) {
-    let serverPubkey = conf.pair ? conf.pair.pub : null;
+    let selfPubkey = conf.pair ? conf.pair.pub : null;
     let rustServerConf = {
       command: commandName,
       currency: conf.currency || "",
       gva: conf.gva,
-      serverPubkey,
+      selfPubkey,
       txsMempoolSize:
         conf.txsMempoolSize || constants.SANDBOX_SIZE_TRANSACTIONS,
     };
@@ -1674,7 +1675,6 @@ export class FileDAL implements ServerDAO {
         unitbase,
         local_iindex
       );
-      // TODO ESZ: call rust server: write_ud_sources(udSources: SimpleUdEntryForWallet[])
       return udSources;
     }
     return [];
diff --git a/app/lib/dto/ConfDTO.ts b/app/lib/dto/ConfDTO.ts
index 7ddc0bbc3d6484d77d55a571a919f6e8367d49dd..b80564a06834daa699c15a152aab5d86b04b3066 100644
--- a/app/lib/dto/ConfDTO.ts
+++ b/app/lib/dto/ConfDTO.ts
@@ -183,9 +183,13 @@ export class ConfDTO
     public gva?: {
       host?: string;
       port?: number;
-      remotehost?: string | null;
-      remoteport?: number | null;
-      remotepath?: string;
+      path?: string;
+      subscriptionsPath?: string;
+      remoteHost?: string;
+      remotePort?: number;
+      remotePath?: string;
+      remoteSubscriptionsPath?: string;
+      remoteTls?: boolean;
     },
     public ws2p?: {
       privateAccess?: boolean;
diff --git a/app/modules/config.ts b/app/modules/config.ts
index 9ff3ced8561b0605258f329b4ce6532cdebe5008..2dfe10269ade0665d43e9f1ae8f39781df5af346 100644
--- a/app/modules/config.ts
+++ b/app/modules/config.ts
@@ -26,6 +26,10 @@ module.exports = {
         value: "--gva",
         desc: "Enable gva API and database.",
       },
+      {
+        value: "--no-gva",
+        desc: "Disable gva API and database.",
+      },
     ],
 
     config: {
@@ -39,13 +43,24 @@ module.exports = {
         if (
           program.gva &&
           program.gva === true &&
-          (!program.nogva || program.nogva === undefined)
+          (!program.noGva || program.noGva === undefined)
         ) {
-          conf.gva = {
-            host: "localhost",
-            port: 30901,
-          };
-        } else if (program.nogva) {
+          // Fill with default conf if needed
+          if (conf.gva) {
+            conf.gva.host = conf.gva.host || "localhost";
+            conf.gva.port = conf.gva.port || 30901;
+            conf.gva.path = conf.gva.path || "gva";
+            conf.gva.subscriptionsPath =
+              conf.gva.subscriptionsPath || "gva-sub";
+          } else {
+            conf.gva = {
+              host: "localhost",
+              port: 30901,
+              path: "gva",
+              subscriptionsPath: "gva-sub",
+            };
+          }
+        } else if (program.noGva) {
           conf.gva = undefined;
         }
       },
diff --git a/app/modules/peersignal.ts b/app/modules/peersignal.ts
index d4f650a7d1dbec7d06d017b74978c6799b633936..a37d6531356def7b65d8e5fb1acbb19936b3cdba 100644
--- a/app/modules/peersignal.ts
+++ b/app/modules/peersignal.ts
@@ -14,6 +14,7 @@
 "use strict";
 import { ConfDTO } from "../lib/dto/ConfDTO";
 import { Server } from "../../server";
+import { PeerDTO } from "../lib/dto/PeerDTO";
 
 const async = require("async");
 const constants = require("../lib/constants");
@@ -56,10 +57,15 @@ class PeerSignalEmitter {
     this.INTERVAL = setInterval(() => {
       this.peerFifo.push(async (done: any) => {
         try {
-          await this.server.PeeringService.generateSelfPeer(
+          let selfPeer = await this.server.PeeringService.generateSelfPeer(
             this.conf,
             SIGNAL_INTERVAL
           );
+          if (selfPeer) {
+            this.server.dal.rustServer.updateSelfPeer(
+              PeerDTO.fromDBPeer(selfPeer)
+            );
+          }
           done();
         } catch (e) {
           done(e);
@@ -68,14 +74,15 @@ class PeerSignalEmitter {
     }, SIGNAL_INTERVAL);
 
     // Launches it a first time few seconds after startup
-    setTimeout(
-      () =>
-        this.server.PeeringService.generateSelfPeer(
-          this.conf,
-          SIGNAL_INTERVAL - SIGNAL_INITIAL_DELAY
-        ),
-      0
-    );
+    setTimeout(async () => {
+      let selfPeer = await this.server.PeeringService.generateSelfPeer(
+        this.conf,
+        SIGNAL_INTERVAL - SIGNAL_INITIAL_DELAY
+      );
+      if (selfPeer) {
+        this.server.dal.rustServer.updateSelfPeer(PeerDTO.fromDBPeer(selfPeer));
+      }
+    }, 0);
   }
 
   stopService() {
diff --git a/doc/use/configure.md b/doc/use/configure.md
index 229eacba4b02984bf220fdbedf67867d82ab1541..4d3d1a371a5975ee59a7fff7fd0a7e9248998251 100644
--- a/doc/use/configure.md
+++ b/doc/use/configure.md
@@ -185,15 +185,21 @@ This mode is optional if only because technically it is sometimes difficult or e
 
 GVA is still disabled by default. To enable it you have to add the option `--gva` during synchronization and at each start of your duniter node (`duniter start --gva`).
 
-GVA is not yet configurable from the command line, but it is possible to use environment variables :
+GVA is not yet configurable from the command line, but it is possible to manually edit `conf.json` file :
 
-| parameter | env var | default value |
+| parameter | type | default value |
 |:-:|:-:|:-:|
-| remote_path | `DUNITER_GVA_REMOTE_PATH` | `/gva`
+| host | string | `"localhost"` |
+| port | number |  `30901` |
+| path | string |  `"gva"` |
+| remotePath | string | `"gva"` |
+| subscriptionsPath | string |  `"gva-sub"` |
+| remoteSubscriptionsPath | string | `"gva-sub"` |
+| remoteTls | boolean |  `false` |
 
-GVA server listen to `localhost:10901/remote_path`
+GVA server listen to `http://<host>:<port>/<remotePath>`
 
-GVA subscriptions websocket server listen to `localhost:10901/gva-sub`
+GVA subscriptions websocket server listen to `ws://<host>:<port>/<remoteSubscriptionsPath>`
 
 ## Synchronize your node
 
diff --git a/neon/native/server.d.ts b/neon/native/server.d.ts
index ca66fa33461c33e68581e7012cdf18c39829db51..0e194c0951b9632e7294788fa44e1485e3f66ec3 100644
--- a/neon/native/server.d.ts
+++ b/neon/native/server.d.ts
@@ -6,13 +6,25 @@ export class RustServerConf {
     command: string | null
     currency: string
     gva: GvaConf | undefined
-    serverPubkey: string | null
+    selfPubkey: string | null
     txsMempoolSize: number
 }
 
 export class GvaConf {
     host?: string
     port?: number
+    path?: string;
+    subscriptionsPath?: string;
+}
+
+export class PeerCard {
+    version: number
+    currency: string
+    pubkey: string
+    blockstamp: string
+    endpoints: string[]
+    signature: string
+    status: string
 }
 
 export class RustDbTx {
@@ -87,4 +99,5 @@ export class RustServer {
     applyBlock(block: BlockDTOV10): void;
     applyChunkOfBlocks(blocks: BlockDTOV10[]): void;
     trimExpiredNonWrittenTxs(limitTime: number): void;
+    updateSelfPeer(peer: PeerCard): void;
 }
diff --git a/neon/native/src/server.rs b/neon/native/src/server.rs
index f89f2344c397389c549c87fb37e1ec3bce0db110..5bf99530dd818821501e6ef85c98765f80c8671d 100644
--- a/neon/native/src/server.rs
+++ b/neon/native/src/server.rs
@@ -21,7 +21,7 @@ use dubp::documents::{
     transaction::{TransactionDocumentV10, TransactionDocumentV10Stringified},
 };
 use dubp::documents_parser::prelude::*;
-use duniter_server::{DuniterServer, DuniterServerConf, GvaConf};
+use duniter_server::{DuniterServer, DuniterServerConf, GvaConf, PeerCardStringified};
 use neon::declare_types;
 use neon::prelude::*;
 use serde::{Deserialize, Serialize};
@@ -47,19 +47,29 @@ declare_types! {
                 if let Some(port) = gva_conf_stringified.port {
                     gva_conf.port(port);
                 }
+                if let Some(path) = gva_conf_stringified.path {
+                    gva_conf.path(path);
+                }
+                if let Some(subscriptions_path) = gva_conf_stringified.subscriptions_path {
+                    gva_conf.subscriptions_path(subscriptions_path);
+                }
                 Some(gva_conf)
             } else {
                 None
             };
             let command_name = rust_server_conf_stringified.command_name;
             let currency = rust_server_conf_stringified.currency;
-            let server_pubkey = if let Some(server_pubkey_str) = rust_server_conf_stringified.server_pubkey {
-                into_neon_res(&mut cx, PublicKey::from_base58(&server_pubkey_str))?
+            let server_pubkey = if let Some(self_pubkey_str) = rust_server_conf_stringified.self_pubkey {
+                into_neon_res(&mut cx, PublicKey::from_base58(&self_pubkey_str))?
             } else {
                 PublicKey::default()
             };
             let txs_mempool_size = rust_server_conf_stringified.txs_mempool_size as usize;
-            let conf = DuniterServerConf { gva: gva_conf, server_pubkey, txs_mempool_size };
+            let conf = DuniterServerConf {
+                gva: gva_conf,
+                self_pubkey: server_pubkey,
+                txs_mempool_size
+            };
 
             let home_path_opt = if let Some(arg1) = arg1_opt {
                 if arg1.is_a::<JsString>() {
@@ -289,6 +299,19 @@ declare_types! {
             }.map(|()| cx.undefined().upcast());
             into_neon_res(&mut cx, res)
         }
+        method updateSelfPeer(mut cx) {
+            let peer_js = cx.argument::<JsValue>(0)?;
+
+            let peer_stringified: PeerCardStringified = neon_serde::from_value(&mut cx, peer_js)?;
+
+            let this = cx.this();
+            {
+                let guard = cx.lock();
+                let server = this.borrow(&guard);
+                server.server.update_self_peer(peer_stringified)
+            };
+            Ok(cx.undefined().upcast())
+        }
     }
 }
 
@@ -298,7 +321,7 @@ struct RustServerConfStringified {
     command_name: Option<String>,
     currency: String,
     gva: Option<GvaConfStringified>,
-    server_pubkey: Option<String>,
+    self_pubkey: Option<String>,
     txs_mempool_size: u32,
 }
 
@@ -307,6 +330,8 @@ struct RustServerConfStringified {
 struct GvaConfStringified {
     host: Option<String>,
     port: Option<u16>,
+    path: Option<String>,
+    subscriptions_path: Option<String>,
 }
 
 #[derive(Deserialize, Serialize)]
diff --git a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs b/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs
index dbdad922ffe65a1b7fa574d1cb1fbf8a6214569f..cf714942acd5200eaaf7b6dd9cdc926017c35fda 100644
--- a/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs
+++ b/rust-libs/duniter-dbs-write-ops/src/gva/tx.rs
@@ -54,7 +54,6 @@ pub(crate) fn write_gva_tx<B: Backend>(
 
                 // Remove consumed UTXOs
                 for input in tx.get_inputs() {
-                    // TODO ESZ remove UD sources
                     if let SourceIdV10::Utxo(utxo_id) = input.id {
                         let db_tx_origin = gva_db
                             .txs()
@@ -147,7 +146,6 @@ pub(crate) fn revert_tx<B: Backend>(
                     }
                     // Recreate UTXOs consumed by this tx
                     for input in tx_db.tx.get_inputs() {
-                        // TODO ESZ recreate UD sources
                         if let SourceIdV10::Utxo(utxo_id) = input.id {
                             let db_tx_origin = gva_db
                                 .txs()
diff --git a/rust-libs/duniter-gva/Cargo.toml b/rust-libs/duniter-gva/Cargo.toml
index c7dc21259e018a9f98057032161a0ac7ea5c1d18..93c56d4099841561d10626e564ef3e3ce353634d 100644
--- a/rust-libs/duniter-gva/Cargo.toml
+++ b/rust-libs/duniter-gva/Cargo.toml
@@ -18,6 +18,7 @@ futures = "0.3.6"
 http = "0.2.1"
 log = "0.4.11"
 resiter = "0.4.0"
+serde = { version = "1.0.105", features = ["derive"] }
 serde_urlencoded = "0.7.0"
 smallvec = { version = "1.4.0", features = ["serde", "write"] }
 tokio = { version = "0.2.22", features = ["io-util", "rt-threaded", "stream"] }
diff --git a/rust-libs/duniter-gva/src/entities.rs b/rust-libs/duniter-gva/src/entities.rs
index d4ceff8b25981f29935fc58d7c09dbd2f8e04c03..77860bf00dd565a5998f9ca10ce9a64d44aa6351 100644
--- a/rust-libs/duniter-gva/src/entities.rs
+++ b/rust-libs/duniter-gva/src/entities.rs
@@ -18,6 +18,18 @@ pub mod ud_gva;
 
 use crate::*;
 
+#[derive(async_graphql::SimpleObject)]
+pub(crate) struct TxsHistoryGva {
+    /// Transactions sent
+    pub(crate) sent: Vec<TxGva>,
+    /// Transactions sending
+    pub(crate) sending: Vec<TxGva>,
+    /// Transactions received
+    pub(crate) received: Vec<TxGva>,
+    /// Transactions receiving
+    pub(crate) receiving: Vec<TxGva>,
+}
+
 #[derive(Clone, async_graphql::SimpleObject)]
 pub(crate) struct UtxoGva {
     /// Source amount
@@ -31,15 +43,3 @@ pub(crate) struct UtxoGva {
     /// Written time
     pub(crate) written_time: i64,
 }
-
-#[derive(async_graphql::SimpleObject)]
-pub(crate) struct TxsHistoryGva {
-    /// Transactions sent
-    pub(crate) sent: Vec<TxGva>,
-    /// Transactions sending
-    pub(crate) sending: Vec<TxGva>,
-    /// Transactions received
-    pub(crate) received: Vec<TxGva>,
-    /// Transactions receiving
-    pub(crate) receiving: Vec<TxGva>,
-}
diff --git a/rust-libs/duniter-gva/src/lib.rs b/rust-libs/duniter-gva/src/lib.rs
index 4c058c92af014c1bb06e9b57a4c56f1bd546a904..7d542244d4f120cec2bab0ad5e72075e4d40b09e 100644
--- a/rust-libs/duniter-gva/src/lib.rs
+++ b/rust-libs/duniter-gva/src/lib.rs
@@ -59,7 +59,7 @@ use warp::{http::Response as HttpResponse, Filter as _, Rejection, Stream};
 pub struct GvaConf {
     host: String,
     port: u16,
-    remote_path: String,
+    path: String,
     subscriptions_path: String,
 }
 
@@ -68,7 +68,7 @@ impl Default for GvaConf {
         GvaConf {
             host: "localhost".to_owned(),
             port: 30901,
-            remote_path: "gva".to_owned(),
+            path: "gva".to_owned(),
             subscriptions_path: "gva-sub".to_owned(),
         }
     }
@@ -81,12 +81,20 @@ impl GvaConf {
     pub fn port(&mut self, port: u16) {
         self.port = port;
     }
-    pub fn remote_path(&mut self, mut remote_path: String) {
-        if remote_path.starts_with('/') {
-            remote_path.remove(0);
-            self.remote_path = remote_path;
+    pub fn path(&mut self, mut path: String) {
+        if path.starts_with('/') {
+            path.remove(0);
+            self.path = path;
         } else {
-            self.remote_path = remote_path;
+            self.path = path;
+        }
+    }
+    pub fn subscriptions_path(&mut self, mut subscriptions_path: String) {
+        if subscriptions_path.starts_with('/') {
+            subscriptions_path.remove(0);
+            self.subscriptions_path = subscriptions_path;
+        } else {
+            self.subscriptions_path = subscriptions_path;
         }
     }
 }
@@ -94,14 +102,19 @@ impl GvaConf {
 #[derive(Clone, Copy, Debug)]
 pub struct GvaServer;
 
+#[derive(Debug, Default)]
+pub struct ServerMetaData {
+    pub currency: String,
+    pub self_pubkey: PublicKey,
+    pub software_version: &'static str,
+}
+
 impl GvaServer {
     pub fn start(
         conf: GvaConf,
-        currency: String,
         dbs: DuniterDbs,
         dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>,
-        server_pubkey: PublicKey,
-        software_version: &'static str,
+        server_meta_data: ServerMetaData,
         txs_mempool: TxsMempool,
     ) -> Result<(), tokio::io::Error> {
         println!("TMP GvaServer::start: conf={:?}", conf);
@@ -117,11 +130,9 @@ impl GvaServer {
                     subscriptions::SubscriptionRoot::default(),
                 )
                 .data(schema::SchemaData {
-                    currency,
                     dbs,
                     dbs_pool,
-                    server_pubkey,
-                    software_version,
+                    server_meta_data,
                     txs_mempool,
                 })
                 .extension(async_graphql::extensions::Logger)
@@ -134,22 +145,20 @@ impl GvaServer {
                 );
 
                 let conf_clone = conf.clone();
-                let graphql_playground = warp::path::path(conf.remote_path.clone())
-                    .and(warp::get())
-                    .map(move || {
-                        HttpResponse::builder()
-                            .header("content-type", "text/html")
-                            .body(async_graphql::http::playground_source(
-                                GraphQLPlaygroundConfig::new(&format!(
-                                    "/{}",
-                                    &conf_clone.remote_path
+                let graphql_playground =
+                    warp::path::path(conf.path.clone())
+                        .and(warp::get())
+                        .map(move || {
+                            HttpResponse::builder()
+                                .header("content-type", "text/html")
+                                .body(async_graphql::http::playground_source(
+                                    GraphQLPlaygroundConfig::new(&format!("/{}", &conf_clone.path))
+                                        .subscription_endpoint(&format!(
+                                            "/{}",
+                                            &conf_clone.subscriptions_path,
+                                        )),
                                 ))
-                                .subscription_endpoint(&format!(
-                                    "/{}",
-                                    &conf_clone.subscriptions_path,
-                                )),
-                            ))
-                    });
+                        });
 
                 let routes = graphql_playground
                     .or(graphql_post)
@@ -171,7 +180,7 @@ impl GvaServer {
                 log::info!(
                     "Start GVA server at http://localhost:{}/{}",
                     conf.port,
-                    &conf.remote_path
+                    &conf.path
                 );
                 warp::serve(routes).run(([0, 0, 0, 0], conf.port)).await;
             });
@@ -181,10 +190,39 @@ impl GvaServer {
     }
 }
 
+#[derive(
+    async_graphql::SimpleObject, Clone, Debug, Default, serde::Deserialize, serde::Serialize,
+)]
+#[serde(rename_all = "camelCase")]
+#[graphql(name = "PeerCard")]
+pub struct PeerCardStringified {
+    pub version: u32,
+    pub currency: String,
+    pub pubkey: String,
+    pub blockstamp: String,
+    pub endpoints: Vec<String>,
+    pub status: String,
+    pub signature: String,
+}
+impl From<duniter_dbs::PeerCardDbV1> for PeerCardStringified {
+    fn from(peer: duniter_dbs::PeerCardDbV1) -> Self {
+        Self {
+            version: peer.version,
+            currency: peer.currency,
+            pubkey: peer.pubkey,
+            blockstamp: peer.blockstamp,
+            endpoints: peer.endpoints,
+            status: peer.status,
+            signature: peer.signature,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
     use duniter_dbs::bc_v2::{BcV2Db, BcV2DbWritable};
+    use duniter_dbs::cm_v1::{CmV1Db, CmV1DbWritable};
     use duniter_dbs::kv_typed::backend::memory::{Mem, MemConf};
     use duniter_dbs::{GvaV1Db, GvaV1DbWritable, TxsMpV2Db, TxsMpV2DbWritable};
     use fast_threadpool::ThreadPoolConfig;
@@ -195,6 +233,7 @@ mod tests {
     fn launch_mem_gva() {
         let dbs = DuniterDbs {
             bc_db: unwrap!(BcV2Db::<Mem>::open(MemConf::default())),
+            cm_db: unwrap!(CmV1Db::<MemSingleton>::open(MemSingletonConf::default())),
             gva_db: unwrap!(GvaV1Db::<Mem>::open(MemConf::default())),
             txs_mp_db: unwrap!(TxsMpV2Db::<Mem>::open(MemConf::default())),
         };
@@ -203,11 +242,9 @@ mod tests {
 
         unwrap!(GvaServer::start(
             GvaConf::default(),
-            "test".to_owned(),
             dbs,
             threadpool.into_async_handler(),
-            PublicKey::default(),
-            "test",
+            ServerMetaData::default(),
             TxsMempool::new(10)
         ));
 
diff --git a/rust-libs/duniter-gva/src/mutations.rs b/rust-libs/duniter-gva/src/mutations.rs
index 770f5be3aaa57f211b7795a9d7df78bb71c90323..dff0edd7411766235053dbfa743aa5a19285a0de 100644
--- a/rust-libs/duniter-gva/src/mutations.rs
+++ b/rust-libs/duniter-gva/src/mutations.rs
@@ -33,7 +33,7 @@ impl MutationRoot {
 
         let data = ctx.data::<SchemaData>()?;
 
-        let server_pubkey = data.server_pubkey;
+        let server_pubkey = data.server_meta_data.self_pubkey;
         let txs_mempool = data.txs_mempool;
 
         let tx = data
@@ -62,7 +62,7 @@ impl MutationRoot {
 
         let data = ctx.data::<SchemaData>()?;
 
-        let server_pubkey = data.server_pubkey;
+        let server_pubkey = data.server_meta_data.self_pubkey;
         let txs_mempool = data.txs_mempool;
 
         let mut processed_txs = Vec::with_capacity(txs.len());
diff --git a/rust-libs/duniter-gva/src/queries.rs b/rust-libs/duniter-gva/src/queries.rs
index e90afc4e4d4bd1044d3c52d6077efe8757cf2e3b..ea08f16cf0718da4cf608e49d62d9d49b882e598 100644
--- a/rust-libs/duniter-gva/src/queries.rs
+++ b/rust-libs/duniter-gva/src/queries.rs
@@ -19,6 +19,7 @@ pub mod uds;
 pub mod utxos;
 
 use crate::*;
+use duniter_dbs::cm_v1::CmV1DbReadable as _;
 
 #[derive(async_graphql::MergedObject, Default)]
 pub struct QueryRoot(
@@ -29,26 +30,39 @@ pub struct QueryRoot(
     queries::utxos::UtxosQuery,
 );
 
-#[derive(async_graphql::SimpleObject)]
-struct Node {
-    /// Software
-    software: &'static str,
-
-    /// Software version
-    version: &'static str,
+#[derive(Default, async_graphql::SimpleObject)]
+struct NodeQuery {
+    node: Node,
 }
 
 #[derive(Default)]
-pub(crate) struct NodeQuery;
+struct Node;
 
 #[async_graphql::Object]
-impl NodeQuery {
-    /// Node informations
-    async fn node(&self, ctx: &async_graphql::Context<'_>) -> async_graphql::Result<Node> {
+impl Node {
+    /// Peer card
+    async fn peer(
+        &self,
+        ctx: &async_graphql::Context<'_>,
+    ) -> async_graphql::Result<Option<PeerCardStringified>> {
+        let data = ctx.data::<SchemaData>()?;
+
+        Ok(data
+            .dbs_pool
+            .execute(move |dbs| dbs.cm_db.self_peer_card().get(&EmptyKey))
+            .await??
+            .map(Into::into))
+    }
+    /// Software
+    async fn software(&self) -> &'static str {
+        "duniter"
+    }
+    /// Software version
+    async fn version(
+        &self,
+        ctx: &async_graphql::Context<'_>,
+    ) -> async_graphql::Result<&'static str> {
         let data = ctx.data::<SchemaData>()?;
-        Ok(Node {
-            software: "duniter",
-            version: data.software_version,
-        })
+        Ok(data.server_meta_data.software_version)
     }
 }
diff --git a/rust-libs/duniter-gva/src/queries/gen_txs.rs b/rust-libs/duniter-gva/src/queries/gen_txs.rs
index a8f25a7f3b4303ccfe32e082552703ad8f838bea..8889f7248bc6783355d8ef0b8c693ffdf3f86bd0 100644
--- a/rust-libs/duniter-gva/src/queries/gen_txs.rs
+++ b/rust-libs/duniter-gva/src/queries/gen_txs.rs
@@ -40,7 +40,7 @@ impl GenTxsQuery {
         let recipient = PublicKey::from_base58(&recipient)?;
 
         let data = ctx.data::<SchemaData>()?;
-        let currency = data.currency.clone();
+        let currency = data.server_meta_data.currency.clone();
 
         let (current_block, inputs, inputs_sum) = data
             .dbs_pool
diff --git a/rust-libs/duniter-gva/src/schema.rs b/rust-libs/duniter-gva/src/schema.rs
index 7d05600c6d86f1eb598dac3811331ca550e6eaa3..9618f6ee785bd8677fb54d5b73933c58c94e4cd7 100644
--- a/rust-libs/duniter-gva/src/schema.rs
+++ b/rust-libs/duniter-gva/src/schema.rs
@@ -21,10 +21,8 @@ pub(crate) type GraphQlSchema = async_graphql::Schema<
     crate::subscriptions::SubscriptionRoot,
 >;
 pub(crate) struct SchemaData {
-    pub(crate) currency: String,
     pub(crate) dbs: DuniterDbs,
     pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>,
-    pub(crate) server_pubkey: PublicKey,
-    pub(crate) software_version: &'static str,
+    pub(crate) server_meta_data: ServerMetaData,
     pub(crate) txs_mempool: TxsMempool,
 }
diff --git a/rust-libs/duniter-gva/src/warp_.rs b/rust-libs/duniter-gva/src/warp_.rs
index 513fe5975969629feb2ae61a2dcfb1b8b0de78af..bc8aba0c7f28f8fa9ac5d2745f2fd9596c9cb40d 100644
--- a/rust-libs/duniter-gva/src/warp_.rs
+++ b/rust-libs/duniter-gva/src/warp_.rs
@@ -55,7 +55,7 @@ pub(crate) fn graphql(
     opts: async_graphql::http::MultipartOptions,
 ) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = Rejection> + Clone {
     let opts = Arc::new(opts);
-    warp::path::path(conf.remote_path.clone())
+    warp::path::path(conf.path.clone())
         .and(warp::method())
         .and(warp::query::raw().or(warp::any().map(String::new)).unify())
         .and(warp::header::optional::<String>("content-type"))
diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs
index 5b35c9d6d70be1e9f0d523ae1b683bd7fac15d6e..e99820f34fdbd0a49e55de3de1c58148a11883ba 100644
--- a/rust-libs/duniter-server/src/lib.rs
+++ b/rust-libs/duniter-server/src/lib.rs
@@ -23,10 +23,11 @@
 )]
 
 pub use duniter_dbs::smallvec;
+use duniter_gva::ServerMetaData;
 use duniter_mempools::{TxMpError, TxsMempool};
 use fast_threadpool::ThreadPoolConfig;
 
-pub use duniter_gva::GvaConf;
+pub use duniter_gva::{GvaConf, PeerCardStringified};
 
 use dubp::common::crypto::keys::ed25519::PublicKey;
 use dubp::common::prelude::*;
@@ -34,6 +35,7 @@ use dubp::documents::{prelude::*, transaction::TransactionDocumentV10};
 use dubp::{
     block::prelude::*, common::crypto::hashs::Hash, documents_parser::prelude::FromStringObject,
 };
+use duniter_dbs::cm_v1::CmV1DbWritable;
 use duniter_dbs::{
     kv_typed::prelude::*, GvaV1DbReadable, HashKeyV2, PendingTxDbV2, TxsMpV2DbReadable,
 };
@@ -51,7 +53,7 @@ pub enum DuniterCommand {
 #[derive(Clone, Debug)]
 pub struct DuniterServerConf {
     pub gva: Option<GvaConf>,
-    pub server_pubkey: PublicKey,
+    pub self_pubkey: PublicKey,
     pub txs_mempool_size: usize,
 }
 
@@ -101,21 +103,16 @@ impl DuniterServer {
                 fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs.clone());
 
             if command != DuniterCommand::Sync {
-                if let Some(mut gva_conf) = conf.gva.clone() {
-                    if let Some(remote_path) = std::env::var_os("DUNITER_GVA_REMOTE_PATH") {
-                        gva_conf.remote_path(
-                            remote_path
-                                .into_string()
-                                .expect("Invalid utf8 for Env var DUNITER_GVA_REMOTE_PATH"),
-                        );
-                    }
+                if let Some(gva_conf) = conf.gva.clone() {
                     duniter_gva::GvaServer::start(
                         gva_conf,
-                        currency,
                         dbs,
                         threadpool.async_handler(),
-                        conf.server_pubkey,
-                        software_version,
+                        ServerMetaData {
+                            currency,
+                            self_pubkey: conf.self_pubkey,
+                            software_version,
+                        },
                         txs_mempool,
                     )
                     .expect("Fail to start GVA server");
@@ -304,6 +301,27 @@ impl DuniterServer {
             })
             .expect("dbs pool disconnected")
     }
+    pub fn update_self_peer(&self, new_peer_card: PeerCardStringified) {
+        self.dbs_pool
+            .execute(move |dbs| {
+                dbs.cm_db
+                    .self_peer_card_write()
+                    .upsert(
+                        EmptyKey,
+                        duniter_dbs::PeerCardDbV1 {
+                            version: new_peer_card.version,
+                            currency: new_peer_card.currency,
+                            pubkey: new_peer_card.pubkey,
+                            blockstamp: new_peer_card.blockstamp,
+                            endpoints: new_peer_card.endpoints,
+                            status: new_peer_card.status,
+                            signature: new_peer_card.signature,
+                        },
+                    )
+                    .expect("fail to write on memory db")
+            })
+            .expect("dbs pool disconnected")
+    }
 }
 
 #[cfg(test)]
@@ -318,7 +336,7 @@ mod tests {
             None,
             DuniterServerConf {
                 gva: None,
-                server_pubkey: PublicKey::default(),
+                self_pubkey: PublicKey::default(),
                 txs_mempool_size: 200,
             },
             "currency_test".to_owned(),
diff --git a/server.ts b/server.ts
index 6cdd3e3dc5a2847aa3e442b8d4f673bb932c5f18..ca8e26559aa8b9f20b4b0184f4a750031b7be4bb 100644
--- a/server.ts
+++ b/server.ts
@@ -47,6 +47,7 @@ import {HttpMilestonePage} from "./app/modules/bma/lib/dtos"
 import * as toJson from "./app/modules/bma/lib/tojson"
 import { rawTxParseAndVerify, txVerify } from "./neon/lib"
 import { TransactionDTOV10 } from "./neon/native"
+import { format } from "util";
 
 export interface HookableServer {
   generatorGetJoinData: (...args:any[]) => Promise<any>
@@ -352,7 +353,8 @@ export class Server extends stream.Duplex implements HookableServer {
   }
 
   async initDAL(conf:ConfDTO|null = null, commandName: string|null = null) {
-    await this.dal.init(this.conf, commandName)
+    this.genGvaEndpoints(this.conf);
+    await this.dal.init(this.conf, commandName);
     // Maintenance
     let head_1 = await this.dal.bindexDAL.head(1);
     if (head_1) {
@@ -381,6 +383,36 @@ export class Server extends stream.Duplex implements HookableServer {
     await this.BlockchainService.forkResolution()
   }
 
+  genGvaEndpoint(conf: ConfDTO): string {
+    return ""
+  }
+  
+  genGvaSubscriptionsEndpoint(conf: ConfDTO): string {
+    return ""
+  }
+
+  genGvaEndpoints(conf:ConfDTO) {
+    if (conf.gva) {
+      let gva = conf.gva;
+      this.addEndpointsDefinitions(async () => format(
+        "GVA %s%s %i %s",
+        (gva.remotePort === 443 || gva.remoteTls === true) ? 'S ':'',
+        gva.remoteHost || gva.host || "localhost",
+        gva.remotePort || gva.port || 80,
+        gva.remotePath || gva.path || ""
+      ));
+      if (gva.remoteSubscriptionsPath || gva.subscriptionsPath) {
+        this.addEndpointsDefinitions(async () => format(
+          "GVASUB %s%s %i %s",
+          (gva.remotePort === 443 || gva.remoteTls === true) ? 'S ':'',
+          gva.remoteHost || gva.host || "localhost",
+          gva.remotePort || gva.port || 80,
+          gva.remoteSubscriptionsPath || gva.subscriptionsPath || ""
+        ));
+      }
+    }
+  }
+
   recomputeSelfPeer(): Promise<DBPeer | null> {
     return this.PeeringService.generateSelfPeer(this.conf)
   }