diff --git a/src/main/java/it/inaf/oats/vospace/SetNodeController.java b/src/main/java/it/inaf/oats/vospace/SetNodeController.java
index 36b2957ac46731f014a23a5335068b7422a059ed..7659ab947f53823a356ff7a46328236d190cdcd2 100644
--- a/src/main/java/it/inaf/oats/vospace/SetNodeController.java
+++ b/src/main/java/it/inaf/oats/vospace/SetNodeController.java
@@ -73,7 +73,7 @@ public class SetNodeController extends BaseNodeController {
         if (node instanceof DataNode) {
             checkViews((DataNode) node, (DataNode) toBeModifiedNode);
         } else if(node instanceof LinkNode) {
-            this.validateInternalLinkNode((LinkNode) node);
+            this.validateInternalLinkNode((LinkNode) node);            
         }
 
         //The service SHOULD throw a HTTP 500 status code including an InternalFault fault 
diff --git a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
index efa2e1adb49dcee0ed8b344a79e7f9f5c5610f0e..2879a00161c7cddefb638f24f2cbb42cd547e539 100644
--- a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
+++ b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
@@ -91,7 +91,7 @@ public class NodeDAO {
             ps.setObject(++i, NodeUtils.getDbNodeType(myNode), Types.OTHER);
             ps.setObject(++i, fromViewsToArray(ps, myNode, d -> d.getAccepts()), Types.OTHER);
             ps.setObject(++i, fromViewsToArray(ps, myNode, d -> d.getProvides()), Types.OTHER);
-            if(myNode instanceof LinkNode) {
+            if (myNode instanceof LinkNode) {
                 ps.setString(++i, ((LinkNode) myNode).getTarget());
             } else {
                 ps.setNull(++i, Types.VARCHAR);
@@ -171,20 +171,31 @@ public class NodeDAO {
 
         String vosPath = URIUtils.returnVosPathFromNodeURI(newNode, authority);
 
-        if (recursive) {
+        boolean isLinkNode = newNode instanceof LinkNode;
+
+        // If is link ignore recursive: LinkNodes are supposed to be childless
+        if (recursive && !isLinkNode) {            
             updatePermissionsRecursively(newNode, vosPath);
         } else {
             jdbcTemplate.update(conn -> {
 
                 String sql = "UPDATE node\n"
-                        + "SET group_read = ?, group_write = ?, is_public = ?"
-                        + "WHERE node_id = id_from_vos_path(?)\n";
+                        + "SET group_read = ?, group_write = ?, is_public = ?\n";
+
+                if (isLinkNode) {
+                    sql += ", target = ?\n";
+                }
+                
+                sql += "WHERE node_id = id_from_vos_path(?)\n";
 
                 PreparedStatement ps = conn.prepareStatement(sql);
                 int i = 0;
                 ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_READ_URI)));
                 ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_WRITE_URI)));
                 ps.setBoolean(++i, Boolean.valueOf(NodeProperties.getNodePropertyByURI(newNode, NodeProperties.PUBLIC_READ_URI)));
+                if (isLinkNode) {
+                    ps.setString(++i, ((LinkNode) newNode).getTarget() );
+                }
                 ps.setString(++i, vosPath);
                 return ps;
             });
@@ -193,6 +204,22 @@ public class NodeDAO {
         return newNode;
     }
 
+    private void setLinkNodeTarget(String nodeVosPath, String target) {
+
+        jdbcTemplate.update(conn -> {
+
+            String sql = "UPDATE node\n"
+                    + "SET target = ?\n"
+                    + "WHERE node_id = id_from_vos_path(?)\n";
+
+            PreparedStatement ps = conn.prepareStatement(sql);
+            int i = 0;
+            ps.setString(++i, target);
+            ps.setString(++i, nodeVosPath);
+            return ps;
+        });
+    }
+
     private Node getNodeFromResultSet(ResultSet rs) throws SQLException {
 
         Node node = NodeUtils.getTypedNode(rs.getString("type"));
diff --git a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
index 1b07a7b29c265e14af1273e4e2cc3d923937b086..c93f3512d7e65018199aed457c82ca9b67cb0254 100644
--- a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
+++ b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
@@ -49,7 +49,7 @@ public class NodeDAOTest {
         dao = new NodeDAO(dataSource);
         ReflectionTestUtils.setField(dao, "authority", AUTHORITY);
     }
-    
+
     @Test
     public void testCreateNode() {
         DataNode dataNode = new DataNode();
@@ -66,22 +66,22 @@ public class NodeDAOTest {
         assertEquals(retrievedNode.getAccepts().get(0).getUri(), dataNode.getAccepts().get(0).getUri());
         assertEquals(retrievedNode.getProvides().get(0).getUri(), dataNode.getProvides().get(0).getUri());
     }
-    
+
     @Test
     public void testCreateLinkNode() {
         LinkNode linkNode = new LinkNode();
-        
+
         String target = "vos://example.com!vospace/myData1";
 
         linkNode.setUri("vos://example.com!vospace/myLink1");
         linkNode.setTarget(target);
 
         dao.createNode(linkNode);
-                
+
         Node retrievedNode = dao.listNode("/myLink1").get();
-        
+
         assertTrue(retrievedNode instanceof LinkNode);
-        assertEquals(target, ((LinkNode) retrievedNode).getTarget());        
+        assertEquals(target, ((LinkNode) retrievedNode).getTarget());
     }
 
     @Test
@@ -106,12 +106,12 @@ public class NodeDAOTest {
         assertFalse(children.isEmpty());
         assertTrue(children.size() == 2);
         assertTrue(children.containsAll(List.of("f4", "f5")));
-        
+
     }
-    
+
     @Test
     public void testGetQuotaAndMD5() {
-        
+
         ContainerNode node = (ContainerNode) dao.listNode("/test1/f1/f2_renamed").get();
         assertEquals("50000", NodeProperties.getNodePropertyByURI(node, NodeProperties.QUOTA_URI));
         DataNode child = (DataNode) node.getNodes().get(0);
@@ -239,7 +239,7 @@ public class NodeDAOTest {
         assertTrue(optId.isPresent());
         assertFalse(dao.isBranchWritable(optId.get(), "user1", List.of("group99")));
     }
-    
+
     @Test
     public void testIsBranchReadable() {
 
@@ -260,29 +260,29 @@ public class NodeDAOTest {
         assertTrue(optId.isPresent());
         assertFalse(dao.isBranchReadable(optId.get(), "user1", List.of("group99")));
     }
-    
+
     @Test
-    public void testSetJobId(){
+    public void testSetJobId() {
         Optional<Long> optId = dao.getNodeId("/test3/m1");
         assertTrue(optId.isPresent());
-        
+
         assertFalse(dao.isBranchBusy(optId.get()));
-        
+
         dao.setBranchJobId(optId.get(), "pippo1");
-        
+
         assertTrue(dao.isBranchBusy(optId.get()));
-        
+
         Optional<Long> childId = dao.getNodeId("/test3/m1/m2");
         assertTrue(childId.isPresent());
-        
+
         assertTrue(dao.isBranchBusy(childId.get()));
-        
+
         dao.setBranchJobId(optId.get(), null);
-        
+
         assertFalse(dao.isBranchBusy(optId.get()));
-        assertFalse(dao.isBranchBusy((childId.get())));    
-               
-    }    
+        assertFalse(dao.isBranchBusy((childId.get())));
+
+    }
 
     @Test
     public void testMoveNodeBranch() {
@@ -311,7 +311,6 @@ public class NodeDAOTest {
 
     }
 
-
     @Test
     public void testCopyNodeBranch() {
         // Let's copy /test3/m1 to /test3/group1
@@ -325,7 +324,7 @@ public class NodeDAOTest {
         assertTrue(optDestParentId.isPresent());
 
         dao.copyBranch("/test3/m1", "/test3/group1/copy_of_m1");
-        
+
         Optional<Long> resultId = dao.getNodeId("/test3/group1/copy_of_m1");
         assertTrue(resultId.isPresent());
 
@@ -445,6 +444,33 @@ public class NodeDAOTest {
         assertEquals("true", NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI));
     }
 
+    @Test
+    public void testSetLinkNodeTarget() {
+
+        Property publicReadProperty = getProperty(NodeProperties.PUBLIC_READ_URI, String.valueOf(false));
+
+        LinkNode node = new LinkNode();
+        node.setUri("vos://example.com!vospace/mylink1");
+        node.getProperties().add(publicReadProperty);
+        node.setTarget("vos://example.com!vospace/mydummytarget1");
+        dao.createNode(node);
+
+        node = (LinkNode) dao.listNode("/mylink1").get();
+        assertEquals("false", NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI));
+        assertEquals("vos://example.com!vospace/mydummytarget1", node.getTarget());
+
+        node.getProperties().clear();
+        publicReadProperty.setValue(String.valueOf(true));
+        node.getProperties().add(publicReadProperty);
+        node.setTarget("vos://example.com!vospace/mydummytarget1_modded");
+
+        dao.setNode(node);
+
+        node = (LinkNode) dao.listNode("/mylink1").get();
+        assertEquals("true", NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI));
+        assertEquals("vos://example.com!vospace/mydummytarget1_modded", node.getTarget());
+    }
+
     @Test
     public void testSetNodeRecursiveGroup() {
 
@@ -493,30 +519,30 @@ public class NodeDAOTest {
     public void testGetNodeOsName() {
         assertEquals("f2", dao.getNodeOsName("/test1/f1/f2_renamed"));
         assertEquals("f4", dao.getNodeOsName("/test2/f4"));
-    }   
-    
+    }
+
     @Test
-    public void testReleaseNodesByJobId(){
+    public void testReleaseNodesByJobId() {
         Optional<Long> optId = dao.getNodeId("/test3/m1");
         assertTrue(optId.isPresent());
-        
+
         assertFalse(dao.isBranchBusy(optId.get()));
-        
+
         dao.setBranchJobId(optId.get(), "pippo1");
-        
+
         assertTrue(dao.isBranchBusy(optId.get()));
-        
+
         Optional<Long> childId = dao.getNodeId("/test3/m1/m2");
         assertTrue(childId.isPresent());
-        
+
         assertTrue(dao.isBranchBusy(childId.get()));
-        
+
         dao.releaseBusyNodesByJobId("pippo1");
-        
+
         assertFalse(dao.isBranchBusy(optId.get()));
-        assertFalse(dao.isBranchBusy((childId.get())));    
-               
-    }       
+        assertFalse(dao.isBranchBusy((childId.get())));
+
+    }
 
     private Property getProperty(String uri, String value) {
         Property property = new Property();